Why fscanf in c reads csv files wrong? - c

I am making a linked list of World Cup teams, when loading the teams I need to do a preload reading data from a csv file but reading 2-word countries makes it wrong
For example
Suppose that this is the csv file:
Arabia Saudita, Herve, Renard, Salman, C, 0, 1
First I read the country name, dt name, captain name, group and two numeric values that are part of the program, but the output is something like this:
Country:Arabia DT:Saudita Herve Renard Salman C 0 1 Captain: empty Group:Empty
The expected output would be
Country: Arabia Saudita DtName:Herve DtSurname:Renard CaptainName:Salman Group: C
I tried to do it with a txt file but it is the same since it reads the spaces and the program fails or prints wrong
This is a part of the code that fails
FILE *chargue = fopen("Precharge.csv", "r");
while (!feof(charge)) {
fscanf(charge, "%s\n", countryAux);
chargecountry(&team, countryAux);
fscanf(charge, "%s\n", nameDTAux);
fscanf(charge, "%s\n", surnameDTAux);
chargenameDT(&team, surnameDTAux, nameDTAux);
chargeCapitan(&team, nameCapaux);
fscanf(charge, "%c\n", &groupAux);
chargegropu(&team, groupAux);
fscanf(charge, "%d\n", &actualscoreaux);
chargeactualscore(&team, actualscoreaux);
fscanf(charge, "%d\n", &faseActualaux);
chargeFase(&team, faseActualaux);
insert(lis, team);
forwards(lis);
}

Your format strings parse single words and do not stop at the , separator.
Parsing the csv file (or any file in general) with fscanf() is not recommended as it is very difficult to recover from errors and newlines are mostly indistinguishable from other white space characters. Furthermore, it is incorrect to use while (!feof(charge)) to run this loop.
You can learn Why is “while( !feof(file) )” always wrong? and you should tell you teacher about this. It is a common mistake to use feof() for this pupose.
You should instead read one line at a time with fgets() and use %nnn[^,] conversion specifiers to parse the character fields (nnn being the maximum field length).
Here is an example:
#include <errno.h>
#include <stdio.h>
#include <string.h>
int main() {
char buf[256];
char countryAux[100];
char nameDTAux[100];
char surnameDTAux[100];
char groupAux;
int actualscoreaux, faseActualaux;
... // declare team, lis...
FILE *chargue = fopen("Precharge.csv", "r");
if (chargue == NULL) {
fprintf(stderr, "cannot open %s: %s\n", "Precharge.csv",
strerror(errno));
return 1;
}
while (fgets(buf, sizeof buf, chargue)) {
if (sscanf(buf, "%99[^,],%99[^,],%99[^,], %c ,%d ,%d",
countryAux, nameDTAux, surnameDTAux,
&groupAux, &actualscoreaux,&faseActualaux) == 6) {
chargecountry(&team, countryAux);
chargenameDT(&team, surnameDTAux, nameDTAux);
chargeCapitan(&team, nameCapaux);
chargegropu(&team, groupAux);
chargeactualscore(&team, actualscoreaux);
chargeFase(&team, faseActualaux);
insert(lis, team);
forwards(lis);
} else {
printf("invalid record: %s", buf);
}
}
fclose(chargue);
return 0;
}

Related

How do I read the last line of a text file in a C program? [duplicate]

This question already has answers here:
Why is “while( !feof(file) )” always wrong?
(5 answers)
Closed 9 months ago.
I'm trying to study the C language and basically what I want to do is read a file and put it into a struct I created, and then later I'll be doing other things with the struct, but I want to get through the first part first. Let's say that I have a text file called captains.txt and the contents are:
picard 95
janeway 90
pike 15
(note that the last line is just 'pike 15')
So I created a program that's like this:
#include <stdio.h>
#include <stdlib.h> //for exit()
#include <string.h>
#include <ctype.h>
struct captain
{
char capName[10];
int number;
};
typedef struct captain captain;
int main()
{
FILE* file = fopen("captain.txt","r");
if (file == NULL)
{
printf("\nerror opening file");
exit(1);
}
else{
printf("\nfile is opened");
}
char buffer[50];
fgets(buffer,50,file);
while (!feof(file))
{
captain c;
sscanf(buffer, "%s %d", &c.capName, &c.number);
printf("\nc captain is: %s %d", c.capName, c.number);
fgets(buffer,50,file);
}
fclose(file);
return 0;
}
The output on my console is
file is opened
c captain is: picard 95
c captain is: janeway 90
Process returned 0 (0x0) execution time : 0.006 s
Press any key to continue.
Hence Captain Pike is missing in space... almost literally because when I add a new line to the text file that it becomes like this:
picard 95
janeway 90
pike 15
(note the newline after 'pike 15')
Then my output becomes correct. So I know that my program doesn't account for the lack of a newline at the end of the file... so how do I solve this?
Compare these two programs, one (mis)using feof() and one not using it at all. The first corresponds closely to the code in the question — it ignores the return value from fgets() to its detriment. The second only tests the return value from fgets(); it has no need to use feof().
eof53.c
#include <stdio.H>
int main(void)
{
char buffer[256];
fgets(buffer, sizeof(buffer), stdin);
while (!feof(stdin))
{
printf("[%s]\n", buffer);
fgets(buffer, sizeof(buffer), stdin);
}
return 0;
}
eof71.c
#include <stdio.H>
int main(void)
{
char buffer[256];
while (fgets(buffer, sizeof(buffer), stdin) != NULL)
printf("[%s]\n", buffer);
return 0;
}
Given a data file abc containing 3 bytes — 0x41 ('A'), 0x42 ('B'), 0x43 ('C') and no newline, I get the following results:
$ eof53 < abc
$ eof71 < abc
[ABC]
$
This was tested on MacOS Big Sur 11.6.6.
Note that fgets() does not report EOF (by returning a null pointer) when reading the (only) incomplete line, but empirically, feof() does report EOF — correctly, since the file input has ended, even though fgets() did return a string (but not a line) of data.
As explained in the canonical Q&A while (!feof(file)) is always wrong!, using feof() rather than testing the return value from the I/O functions leads to bad results.

how to print \\ in C? (fprintf)

The question how to print one \ is already asked for many times.
I couldn't find anything about printing two backslashes (\\).
When I try to write this:
fputs("\\\\",w_ptr);
there won't be more backslashes than one.
If you are interested:
it's a custom bill writing program which creates Latex PDF with a csv feed.
And there are a lot of double-backslashes in there which indicate a new line feed.
Thanks in advance!
Since you already know how to print one backslash, printing two of them should be easy.
fprintf(file, "%s\n", "\\"); // one backslash
fprintf(file, "%s\n", "\\\\"); // two of them
Oh, and always activate compiler warnings. The first argument to fprintf must be a file pointer, not a string.
Sample program to print two backslashes in file sample.txt:
#include <stdio.h>
#include <stdlib.h>
int main ( void )
{
FILE *fp = NULL;
fp = fopen ("sample.txt", "w+");
if ( !fp )
{
printf ("[ERROR]: Opening sample.txt");
}
fprintf (fp, "%s\n", "\\\\");
fclose (fp);
return 0;
}

Parsing file into an array [duplicate]

This question already has an answer here:
what's the preferred library for CSV parsing/writing in C++? [closed]
(1 answer)
Closed 7 years ago.
Good day. Don't know whether this question has been asked before. Any who, I have a text file with contents like below
AP0003;Football;13.50;90
AP0004;Skateboard;49.90;30
It is basically,
Item Code;Item Name;Price per unit;Quantity
I am trying to put the contents of the text file into an array but I've had no luck so far. And, I can't find anything similar on Stack Overflow (or maybe my search parameters is not accurate). Would appreciate any help I can get. Am new to C Programming.
Firstly open the file using fopen:
FILE* fp = fopen("NAME_OF_FILE.txt", "r"); // "r" stands for reading
Now, check if it opened
if(fp == NULL) //If fopen failed
{
printf("fopen failed to open the file\n");
exit(-1); //Exit program
}
Suppose that these are your arrays to store the line and each data are:
char line[2048]; //To store the each line
char itemCode[50];
char item[50];
double price;
int quantity; //Variables to store data
Read the file using fgets. It consumes line by line. Put it in a loop which terminates when fgets returns NULL to scan the whole file line by line. Then extract data from the scanned line using sscanf. It, in this case, will return 4 if successful:
while(fgets(line, sizeof(line), fp) != NULL) //while fgets does not fail to scan a line
{
if(sscanf(line, "%[^;];%[^;];%lf;%d", itemCode, item, price, quantity) != 4) //If sscanf failed to scan everything from the scanned line
//%[^;] scans everything until a ';'
//%lf scans a double
//%d scans an int
//Better to use `"%49[^;];%49[^;];%lf;%d"` to prevent buffer overflows
{
printf("Bad line detected\n");
exit(-1); //Exit the program
}
printf("ItemCode=%s\n", itemCode);
printf("Item=%s\n", item);
printf("price=%f\n", price);
printf("Quantity=%d\n\n", quantity); //Print scanned items
}
Finally, close the file using fclose:
fclose(fp);
You can try this code :
#include <stdio.h>
#include <stdlib.h>
int main()
{
char str1[1000],ch;
int i=0;
FILE *fp;
fp = fopen ("file.txt", "r"); //name of the file is file.txt
while(1)
{
fscanf(fp,"%c",&ch);
if(ch==EOF) break; //end of file
else str[i++]=ch; //put it in an array
}
fclose(fp);
return(0);
}
This will put your entire file into an array str including '\n' and other special characters.If you dont want the special characters put neccessary conditions in the while loop.

Automated interactive programming

I apologize in advance for any orthographic or grammatical error due to the fact that English is not my mother tongue.
I'm new to HTML and I've made a C program to automate a repetitive encoding (creating button spoilers, asking for the hidden content and what's written on the button each time)
The thing is that I've been forced to convert all the text (array of char) I wanted to write in hexadecimal because it contained some of the reserved characters of C language...
The program runs smoothly and fits my needs for the moment but I'd like to know if there is another way than converting everything into hex.
Also, gcc gives me this warning twice :
format ‘%s’ expects argument of type ‘char ’, but argument 2 has type ‘char ()[50]’ [-Wformat]
after these kinds of lines :
scanf("%s", &hidden_text);
(hidden_text is an array of char initialized like :
char hidden_text[50];)
how do I fix that warning ? passing a %50s to scanf didn't work (the program ran but this warning bothers me and I'd be glad if anyone tell me a way out of it)
If anyone see a way of upgrading that program or have any hint, please help out the new programmer I am.
(just for the record, I'm using linux, Emacs is my IDE and I'm using gcc to compile)
Here is the source code (hope I don't get reported for posting too much text):
#include<stdlib.h>
#include<stdio.h>
#include<string.h> /*strlen use this*/
int number_of_spoilers=10; /* the number of spoiler buttons you want to create (changed that value so you can test fast)*/
int a=0;
int spoiler=0; /*the spoiler Id I need to pass between each part*/
char part0[14]="\x3c\x68\x74\x6d\x6c\x3e\x0d\x0a\x3c\x62\x6f\x64\x79\x3e";
char part1[9]="\x3c\x64\x69\x76\x20\x69\x64\x3d\x22";
char part2[23]="\x22\x20\x73\x74\x79\x6c\x65\x3d\x22\x64\x69\x73\x70\x6c\x61\x79\x3a\x6e\x6f\x6e\x65\x22\x3e";
char hidden_text[50];
char part3[100]="\x3c\x2f\x64\x69\x76\x3e\x3c\x62\x75\x74\x74\x6f\x6e\x20\x74\x69\x74\x6c\x65\x3d\x22\x43\x6c\x69\x63\x6b\x20\x74\x6f\x20\x73\x68\x6f\x77\x2f\x68\x69\x64\x65\x20\x63\x6f\x6e\x74\x65\x6e\x74\x22\x20\x74\x79\x70\x65\x3d\x22\x62\x75\x74\x74\x6f\x6e\x22\x20\x6f\x6e\x63\x6c\x69\x63\x6b\x3d\x22\x69\x66\x28\x64\x6f\x63\x75\x6d\x65\x6e\x74\x2e\x67\x65\x74\x45\x6c\x65\x6d\x65\x6e\x74\x42\x79\x49\x64\x28\x27";
char part4[53]="\x27\x29\x20\x2e\x73\x74\x79\x6c\x65\x2e\x64\x69\x73\x70\x6c\x61\x79\x3d\x3d\x27\x6e\x6f\x6e\x65\x27\x29\x20\x7b\x64\x6f\x63\x75\x6d\x65\x6e\x74\x2e\x67\x65\x74\x45\x6c\x65\x6d\x65\x6e\x74\x42\x79\x49\x64\x28\x27";
char part5[51]="\x27\x29\x20\x2e\x73\x74\x79\x6c\x65\x2e\x64\x69\x73\x70\x6c\x61\x79\x3d\x27\x27\x7d\x65\x6c\x73\x65\x7b\x64\x6f\x63\x75\x6d\x65\x6e\x74\x2e\x67\x65\x74\x45\x6c\x65\x6d\x65\x6e\x74\x42\x79\x49\x64\x28\x27";
char part6[27]="\x27\x29\x20\x2e\x73\x74\x79\x6c\x65\x2e\x64\x69\x73\x70\x6c\x61\x79\x3d\x27\x6e\x6f\x6e\x65\x27\x7d\x22\x3e";
char button_text[50];
char part7[9]="\x3c\x2f\x62\x75\x74\x74\x6f\x6e\x3e";
char part_end[16]="\x3c\x2f\x68\x74\x6d\x6c\x3e\x0d\x0a\x3c\x2f\x62\x6f\x64\x79\x3e";
FILE *f=NULL;
main(FILE *f)
{
f=fopen("/home/Spoilers.html","a");
if(f==NULL)
printf("Can't open file");
else{
fwrite(part0, sizeof(char), 14,f);
while(a!=number_of_spoilers){
printf("%s","button text ? :");
scanf("%s", &button_text);
printf("%s", "hidden text ? :");
scanf("%s", &hidden_text);
fwrite(part1, sizeof(char), 9,f);
char hex[5];
sprintf(hex, "%x", spoiler); /*change the spoilerId value to hexa*/
fwrite(&hex, sizeof(char), strlen(hex),f);
fwrite(part2, sizeof(char), 23,f);
fwrite(hidden_text, sizeof(char), strlen(hidden_text),f);
fwrite(part3, sizeof(char), 100,f);
fwrite(&hex, sizeof(char), strlen(hex),f);
fwrite(part4, sizeof(char), 53,f);
fwrite(&hex, sizeof(char), strlen(hex),f);
fwrite(part5, sizeof(char), 51,f);
fwrite(&hex, sizeof(char), strlen(hex),f);
fwrite(part6, sizeof(char), 27,f);
fwrite(button_text, sizeof(char), strlen(button_text),f);
fwrite(part7, sizeof(char), 9, f);
a=a+1; spoiler=spoiler+1;
}
fwrite(part_end, sizeof(char), 16,f); /*contain "</body></html>"*/
fclose(f);
}
}
Thanks by advance and have a good day (or night) !!
If you use scanf( "%s", ... ), the expcected argument is a char * because it just needs the address to copy the input into. If you declare char hidden_text[50]; then hidden_text already is the (constant) pointer to that array. So you have to call
scanf( "%s", hidden_text );
not
scanf( "%s", &hidden_text );
Even better is calling
scanf( "%49s", hidden_text );
to prevent your progam from crashing if the input is too long (note that the length within the format string doesn't include the terminating '\0').
Please try
scanf("%s", &hidden_text[0]);
because you have to pass the address of the first character of the string.
Others have already pointed out the cause of the warning with scanf. Your program has other issues, most of them stylistic.
You are not using a legal form of ´main´ - This should also give a warning in gcc:
main(FILE *f) ...
The function main is special in that it can only have certain signatures. Passing in a file handle is not one of them. (You're also masking your global variable FILE *f, which doesn't hurt in your case, but that's probably not what you wanted.) In your case, where you don't use any command-line arguments, you should use:
int main() ...
Your output is text, so you should use the output functions suited for null-terminated strings, fprintf, putc or fputs. The function fwrite writes raw data lof a certain length and can be used, but you'll always have to pass the correct string length. Speaking of which: Passing constant string lengths to hex-encoded strings like this:
fwrite(part2, sizeof(char), 23,f);
is recipe for disaster: What if your string changes? You'll have to update the call, too. You should at least use strlen(part2) instead of the constant 23.
You read your input with scanf. This is okay, but maybe not the best way: The strings scanned with scanf cannot contain spaces, they are, in effect, single words. You can use the %[...] syntax to specify which characers to read, but that's complicated in my opinion. I propose using fgets, which reads a whole line. (The resulting string does have a trailing newline, which you should remove before processing.)
The number of buttons is fixed in your program. That's okay for a simple program, but ultimately you want the number of buttons to be flexible. It would therefore be better to read until the end of input (Ctrl-D on Unix, Ctrl-Z on Windows). The input functions return special values to indicate the the end of input has been reached: scanf returns EOF and fgets returns NULL in that case.
The strings you write out as spoiler and button text should be "sanitised", i.e. characters that are special to HTML should be masked, such that the input <copy & paste> reads <copy & paste> in the output file.
And a final note: You write out the (longish) code to show and hide buttons for every button. You could shorten that by writing a function for this once and then calling that function.
Putting all that together, your program might now look like this:
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
void print_html(FILE *f, const char *str)
{
while (*str) {
switch (*str) {
case '<': fprintf(f, "<"); break;
case '>': fprintf(f, ">"); break;
case '&': fprintf(f, "&"); break;
default: putc(*str, f);
}
str++;
}
}
int main()
{
FILE *f = fopen("Spoilers.html", "w");
int elid = 0;
if (f == NULL) {
fprintf(stderr, "Can't open file\n");
exit(0);
}
fprintf(f, "<html>\n<head>\n");
fprintf(f, "<script type=\"text/javascript\">\n");
fprintf(f, " function show_hide(elid) {\n");
fprintf(f, " var el = document.getElementById(elid);\n");
fprintf(f, " if (el) {\n");
fprintf(f, " if (el.style.display == 'none') {\n");
fprintf(f, " el.style.display = '';\n");
fprintf(f, " } else {\n");
fprintf(f, " el.style.display = 'none';\n");
fprintf(f, " }\n");
fprintf(f, " }\n");
fprintf(f, " }\n");
fprintf(f, "</script>\n");
fprintf(f, "</head>\n<body>\n");
for (;;) {
char button[50];
char hidden[50];
if (fgets(button, 50, stdin) == NULL) break;
button[strlen(button) - 1] = '\0';
if (fgets(hidden, 50, stdin) == NULL) break;
hidden[strlen(hidden) - 1] = '\0';
fprintf(f, "<div id=\"%04x\" style=\"display:none\">", elid);
print_html(f, hidden);
fprintf(f, "</div><button title=\"Click to show/hide content\" "
"type=\"button\" onclick=\"show_hide('%04x')\">", elid);
print_html(f, button);
fprintf(f, "</button>\n");
elid++;
}
fprintf(f, "</body>\n</html>\n");
fclose(f);
return 0;
}

Read one string at a time from a file in C

How do I read input one string at a time to call another function in C. I thought this would work, but my output hangs:
#define BUFFMT "%255"
#define LINE_LEN 256
#define START_COUNT 1
// filename is declared in the main file elsewhere. I know the file opens since I tried an //old method I use to read one line at time using fgets, but I didn't know how to do one //string at a time. Thanks.
FILE *OpenFile(const char *fileName)
{
FILE *fptr;
if ((fptr = fopen(fileName, "r")) == NULL) {
fprintf(stderr, "Error opening file %s, exiting...", fileName);
exit(EXIT_FAILURE);
}
return fptr;
}
LIST *CreateList(FILE *fp)
{
char buf[LINE_LEN];
while (scanf(BUFFMT"s", buf) != EOF) {
printf("%s: \n", buf);
}
}
scanf() is going to read from the terminal, so it's going to hang waiting for you to type in your input. Use fscanf(fp, BUFFMT"s", buf) instead.
Try this instead of your scanf:
fgets (buf, sizeof (buf), fp)
Have you tried using fgets()
fgets()
fgets() reads up to size-1 characters
from stream and stores them in buffer.
fgets() stores the null character
('\0') after the last character read
into the buffer and returns 'buffer'
if everything works fine, or NULL on
error or end of file.

Resources