Jag håller på och lär mig lite programmering i C.
Det ligger en csv under min C disk som jag skrivit in "testar + radnummer," några rader nedåt.
Dvs:
testar1,
testar2,
testar3, osv osv.
Jag vill läsa de 5 senaste raderna i denna filen, alltså börja längst ned och gå uppåt. Så att output blir:
testar5
testar4
testar3
testar2
testar1
Men jag får inte detta att funka. Den output jag får blir:
testar1
testar1
testar1
testar1
testar1
Vad har jag gjort för fel? Finns det något annat sätt att göra det på? har googlat och läst i timmar men tycker mig inte finna svaren på mina frågor.
min kod:
Kod:
#include <stdio.h>
#include <string.h>
int main() {
int i;
char line[200];
char *token;
FILE *fp;
for (i = 0; i <= 5; i++) {
fp = fopen("C:/test/testfil.csv", "r");
while (fgets(line, sizeof(line), fp)) {
fseek(fp, i, SEEK_END);
fgets(line, sizeof(line), fp);
token = strtok(line, ",");
while (token != NULL) {
printf("%s", token);
token = strtok(NULL, ",");
}
printf("\n");
}
}
fclose(fp);
}
Jag håller på och lär mig lite programmering i C.
Det ligger en csv under min C disk som jag skrivit in "testar + radnummer," några rader nedåt.
Dvs:
testar1,
testar2,
testar3, osv osv.
Jag vill läsa de 5 senaste raderna i denna filen, alltså börja längst ned och gå uppåt. Så att output blir:
testar5
testar4
testar3
testar2
testar1
Men jag får inte detta att funka. Den output jag får blir:
testar1
testar1
testar1
testar1
testar1
Vad har jag gjort för fel? Finns det något annat sätt att göra det på? har googlat och läst i timmar men tycker mig inte finna svaren på mina frågor.
min kod:
Kod:
#include <stdio.h>
#include <string.h>
int main() {
int i;
char line[200];
char *token;
FILE *fp;
for (i = 0; i <= 5; i++) {
fp = fopen("C:/test/testfil.csv", "r");
while (fgets(line, sizeof(line), fp)) {
fseek(fp, i, SEEK_END);
fgets(line, sizeof(line), fp);
token = strtok(line, ",");
while (token != NULL) {
printf("%s", token);
token = strtok(NULL, ",");
}
printf("\n");
}
}
fclose(fp);
}
Länge sen jag skrev nåt i C, men den där algoritmen ser ju aningen sned ut.
Du har ju en loop och det är ju helt fine, men varför öppnar du filen för läsning för varje varv i denna loop?
Det borde ju vara så att först öppnar du filen
Sen med hjälp av din loop läser du in en rad från filen och gör något med den.
När du är klar med din loop stänger du filen.
Ett mer standardiserat och portabelt sätt att lösa det borde vara att läsa igenom filen, och spara de fem sista raderna.
Tjena,
Tanken var att jag skulle slippa söka igenom hela filen, ponera att det skulle finnas 10 000 rader i filen.
Vore ju smidigare att börja nedifrån och sedan med hjälp av en for loop iterera offseten tänkte jag.
"Description
The C library function int fseek(FILE *stream, long int offset, int whence) sets the file position of the stream to the given offset."
Tanken var att jag skulle slippa söka igenom hela filen, ponera att det skulle finnas 10 000 rader i filen.
Vore ju smidigare att börja nedifrån och sedan med hjälp av en for loop iterera offseten tänkte jag.
"Description
The C library function int fseek(FILE *stream, long int offset, int whence) sets the file position of the stream to the given offset."
Ja, fseek i sig funkar troligen bra, men just SEEK_END verkar inte portabelt.
Vet faktiskt inte riktigt hur man läser filer bakvägen på ett effektivt sätt. Brukar "fuska" och använda tail när jag behöver de sista raderna, för den är effektiv. Den borde förvisso vara skriven i C, så det går att kolla hur de gjort.
__________________
Senast redigerad av mulpac 2021-01-07 kl. 18:06.
SEEK_END searches from the one-past last byte of the file:
1234567890 <--- bytes from the file
0123456789A <--- SEEK_SET-relative position
A9876543210 <--- SEEK_END-relative position (absolute value)
Gjorde om min kod till:
Kod:
int i;
char line[200];
char *token;
FILE *fp;
fp = fopen("C:/test/testfil.csv", "r");
fseek(fp, -50, SEEK_END); //Tolkar detta som att den kommer gå från sista byten och-
//sedan 50 bytes bakåt
while (fgets(line, sizeof(line), fp)) {
char* token;
token = strtok(line, ",");
while (token != NULL) {
printf("%s", token);
token = strtok(NULL, ",");
}
printf("\n");
}
}
Detta gjorde att de sista 5 raderna blev printade. Problemet verkar ju vara att jag måste veta hur stor varje rad är i bytes och på något vis backa så många rader?
Detta gjorde att de sista 5 raderna blev printade. Problemet verkar ju vara att jag måste veta hur stor varje rad är i bytes och på något vis backa så många rader?
Läste det du länkade och fick ett humm om vad jag egentligen letade efter, och hittade flertal länkar till trådar där folk velat ungefär samma som jag. Stötte t.ex på denna.
Backa tills du hittar nyradstecknet för respektive rad.
Har försökt med följande kod:
Kod:
int main() {
#define MAX 1024
int i;
int linecount = 5;
int letter = 0;
char ch[MAX];
FILE* fp;
fp = fopen("C:/test/testfil.csv", "r");
i = 1;
fseek(fp, -i, SEEK_END);
letter = fgetc(fp);
if (letter != 0x0a) { // 0x0a == '\n'
i--;
}
else {
fgets(ch, MAX, fp);
printf("%s", ch);
}
}
Tanken är att stega igenom från slutet och gå bakåt tills dess att programmet stöter på en new line "0x0a".
När den gör det läser programmet från den pointern tills dess att raden tar slut med hjälp av "fgets".
Blir dock bara en massa kvadrater i terminalen när jag gör på detta viset, så något utförs inte korrekt.
int main() {
#define MAX 1024
int i;
int linecount = 5;
int letter = 0;
char ch[MAX];
FILE* fp;
fp = fopen("C:/test/testfil.csv", "r");
i = 1;
fseek(fp, -i, SEEK_END);
letter = fgetc(fp);
if (letter != 0x0a) { // 0x0a == '\n'
i--;
}
else {
fgets(ch, MAX, fp);
printf("%s", ch);
}
}
Tanken är att stega igenom från slutet och gå bakåt tills dess att programmet stöter på en new line "0x0a".
När den gör det läser programmet från den pointern tills dess att raden tar slut med hjälp av "fgets".
Blir dock bara en massa kvadrater i terminalen när jag gör på detta viset, så något utförs inte korrekt.
Tog du bort while loopen? Nu läses väl bara absolut sista tecknet en gång.
När du backar kan du ju ha en variabel med antalet hittade 0x0a, när den har värdet 5 läser du framlänges till eof.
Tog du bort while loopen? Nu läses väl bara absolut sista tecknet en gång.
När du backar kan du ju ha en variabel med antalet hittade 0x0a, när den har värdet 5 läser du framlänges till eof.
Jag testade fseek funktionen manuellt genom att skriva offseten själv, och funktionen hittade inget förrän på offset = 5.
Så jag satte i = 5 för att börja iterera från 5, och fram tills det blev en new line.
Detta resulterade i följande kod:
Kod:
int main() {
#define MAX 1024
int i = 5; <-------------
int len;
char line[200];
char* token;
int linecount = 5;
int letter = 0;
char ch[MAX];
FILE* fp;
fp = fopen("C:/test/testfil.csv", "r");
while (letter != 0x0a) {
letter = fgetc(fp);
fseek(fp, -i, SEEK_END); //-i för att stega bakåt i raden
printf("%c\t", letter); //printar varje char
printf("%d\n", i); //printar varje iteration
i++;
}
fclose(fp);
}
Nu får jag åtminstone ut något, men jag inte riktigt sätta fingret på vad som händer.
Terminalen printar ut:
t 5
r 6
a 7
t 8
s 9
e 10
t 11
12
= tratset, nästan "testar7," baklänges, vilket jag förväntade mig.
Varför hittar den inte "," och "7"?
Varför printar den en 12a men inget mer? 12an borde vara 7an. Kan inte 7 behandlas som en char?
Flashback finansieras genom donationer från våra medlemmar och besökare. Det är med hjälp av dig vi kan fortsätta erbjuda en fri samhällsdebatt. Tack för ditt stöd!
Stöd Flashback
Swish: 123 536 99 96Bankgiro: 211-4106
Stöd Flashback
Flashback finansieras genom donationer från våra medlemmar och besökare. Det är med hjälp av dig vi kan fortsätta erbjuda en fri samhällsdebatt. Tack för ditt stöd!