hi I have this question with reading data into array of structures
This is what i have so far:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_NAME 20
#define FILE_NAME 50
#define LIST_SIZE 50
//void getData(RECORD name[], RECORD score)
typedef struct
{
char *name;
int score;
}RECORD;
int main (void)
{
// Declarations
FILE *fp;
char fileName[FILE_NAME];
RECORD list[LIST_SIZE];
char buffer[50];
int count = 0;
// Statements
printf("Enter the file name: ");
gets(fileName);
fp = fopen(fileName, "r");
if(fp == NULL)
printf("Error cannot open the file!\n");
while (fgets(buffer, LIST_SIZE, fp) != NULL)
{
printf("%s\n", buffer);
list[count].name = (char*) calloc(strlen(buffer), sizeof(char));
sscanf(buffer,"%s%d", list[count].name, &list[count].score);
printf("name is: %s and score is:%d \n", list[count].name, list[count].score);
count++;
}
printf("Read in %d data records\n", count);
return 0;
}
so, inside the while loop when i try to print out with out allocating name it seems to work fine, but after i allocate memory for name the buffer is missing the first name when printing out.
so i have this output
Enter the file name: in.txt
Ada Lovelace, 66
Torvalds, 75
Norton, 82
Thompson, 82
Wozniak, 79
Andreessen, 60
Knuth, 60
Goldberg, 71
Hopper, 82
Joy, 91
Tanenbaum, 71
Kernighan, 72
Read in 12 data records
instead of the right output which is
Enter the file name: in.txt
Ada Lovelace, 66
Linus Torvalds, 75
Peter Norton, 82
Ken Thompson, 82
Steve Wozniak, 79
Marc Andreessen, 60
Donald Knuth, 60
Adele Goldberg, 71
Grace Hopper, 82
Bill Joy, 91
Andrew Tanenbaum, 71
Brian Kernighan, 72
Read in 12 data records
This is the output after i commented out the fscanf line, so I think the error may occur there.Is there something thing wrong with the memory allocation process, I'm thinking that I'm doing it wrong.
I fix the fscanf statement now i get
Enter the file name: in.txt
Ada Lovelace, 66
name is: Ada and score is:3929744
Linus Torvalds, 75
name is: Linus and score is:3929752
Peter Norton, 82
name is: Peter and score is:3929760
Ken Thompson, 82
name is: Ken and score is:3929768
Steve Wozniak, 79
name is: Steve and score is:3929776
Marc Andreessen, 60
name is: Marc and score is:3929784
Donald Knuth, 60
name is: Donald and score is:3929792
Adele Goldberg, 71
name is: Adele and score is:3929800
Grace Hopper, 82
name is: Grace and score is:3929808
Bill Joy, 91
name is: Bill and score is:3929816
Andrew Tanenbaum, 71
name is: Andrew and score is:3929824
Brian Kernighan, 72
name is: Brian and score is:3929832
Read in 12 data records
as you can see the line name is: only print out first name but not last name and the address of integer score.
The fgets and the fscanf are fighting with each other because they're both reading from the file. Use fgets to read from the file into your buffer, then use sscanf to parse the data into the structure.
In general you should prefer fgets to fscanf because it's safer. In any case, don't mix fgets and fscanf.
There are several problems with your code. First of all try using scanf and fscanf if there is a certain pattern in your input file. I have had problems with newline characters when using fgets and gets. Also fscanf reads till it finds either space character or the newline (have you considered this in your code? since it is very obvious why it reads only one of the name segments). It may be that your are using printf with the same problem, it only writes till \n or ' '.
You might wanna consider using ifstream and sstream if you can use C++.
Try this one:
...
while (fgets(buffer, LIST_SIZE, fp) != NULL)
{
char *tok;
printf("%s\n", buffer);
tok = strchr(buffer, ',');
if (!tok)
{
printf("Bad line\n");
continue;
}
list[count].name = strndup(buffer, tok - buffer);
list[count].score = atoi(tok + 1);
printf("name is: %s and score is:%d \n", list[count].name, list[count].score);
count++;
}
...
Related
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.
I have a text file that has a structure like:
P2
# CREATOR: GIMP PNM Filter Version 1.1
445 243
255
108
107
104
102
102
[...]
And i want to read this text file line by line. So i writed this code:
int main(void) {
char str[50];
FILE *fp;
fp = fopen("/home/user/Downloads/file.pgm", "r");
if(fp == NULL)
{
printf("Error opening file\n");
exit(1);
}
printf("Testing fgets() function: \n\n");
printf("Reading contents of myfile.txt: \n\n");
while( fgets(str, 30, fp) != NULL )
{
puts(str);
}
fclose(fp);
return 0;
}
However, it gives a strange output. And i don't know where is the error. The code seems ok. What do you think ?
Execution :
You're limiting the fgets to 30 chars, and the comment
# CREATOR: GIMP PNM Filter Version 1.1
is 38 characters.
it is simple fgets also return the \n when it is read (it is not discarded) and writing by puts you add an other \n after the print, so you have 2 \n creating an empty line
Replace puts(str); by fputs(stdout, str); and you will not have the empty lines
Note : the output doesn't correspond to the beginning of the file, may be its end ?
if I put
P2
# CREATOR: GIMP PNM Filter Version 1.1
445 243
255
108
107
104
102
102
in the file the execution gives :
pi#raspberrypi:/tmp $ ./a.out
Testing fgets() function:
Reading contents of myfile.txt:
P2
# CREATOR: GIMP PNM Filter Ve
rsion 1.1
445 243
255
108
107
104
102
102
one line is cut because has more than 29 characters
I am trying to loop over stdin, but since we cannot know the length of stdin, I am not sure how to create the loop or what condition to use in it.
Basically my program will be piped in some data. Each line in the data contains 10 characters of data, followed by a line break (So 11 characters per line)
In pseudocode, what I am trying to accomplish is:
while stdin has data:
read 11 characters from stdin
save 10 of those characters in an array
run some code processing the data
endwhile
Each loop of the while loop rewrites the data into the same 10 bytes of data.
So far, I have figured out that
char temp[11];
read(0,temp,10);
temp[10]='\0';
printf("%s",temp);
will take the first 11 characters from stdin,and save it. The printf will later be replaced by more code that analyzes the data. But I don't know how to encapsulate this functionality in a loop that will process all my data from stdin.
I have tried
while(!feof(stdin)){
char temp[11];
read(0,temp,11);
temp[10]='\0';
printf("%s\n",temp);
}
but when this gets to the last line, it keeps repeatedly printing it out without terminating. Any guidance would be appreciated.
Since you mention line breaks, I assume your data is text. Here is one way, when you know the line lengths. fgets reads the newline too, but that is easily ignored. Instead of trying to use feof I simply check the return value from fgets.
#include <stdio.h>
int main(void) {
char str[16];
int i;
while(fgets(str, sizeof str, stdin) != NULL) { // reads newline too
i = 0;
while (str[i] >= ' ') { // shortcut to testing newline and nul
printf("%d ", str[i]); // print char value
i++;
}
printf ("\n");
str[i] = '\0'; // truncate the array
}
return 0;
}
Program session (ended by Ctrl-Z in Windows console, Ctrl-D in Linux)
qwertyuiop
113 119 101 114 116 121 117 105 111 112
asdfghjkl;
97 115 100 102 103 104 106 107 108 59
zxcvbnm,./
122 120 99 118 98 110 109 44 46 47
^Z
I am trying to run my code on eclipse with ubuntu.
I have dumped the data using fprintf into one txt file and reading that file by using fscanf. I am not able to read that values into data array.
Below is my code :
#include <stdio.h> /* printf, scanf, NULL */
#include <stdlib.h> /* malloc, free, rand */
int main(){
char* data;
FILE *fp;
size_t result;
data = (char*) malloc (sizeof(char)*(1280*800));//Size of one frame
if (data==NULL){
printf("NOt able to allocate memory properly\n");
exit (1);
}
fp = fopen ("\\home\\studinstru\\Desktop\\filedump.txt", "r");
if(fp==NULL){
printf("Error in creating dump file\n");
exit (1);
}
for(int m = 0;m<1280;m++){
for(int n = 0;n<800;n++){
fscanf(fp,"%d/t",data[m*800 + n]);
}
}
fclose(fp);
return 0;
}
This is my filedump.txt data :
79 78 78 77 78 79 81 95
82 81 81 81 82 82 82 82
79 78 78 77 78 79 81 95
82 81 81 81 82 82 82 82
79 78 78 77 78 79 81 95
82 81 81 81 82 82 82 82 ....
Can you tell what is wrong in this?
Your code has a couble of problems
Your fscanf() format is wrong and you are passing the value instead of it's address, you should use
fscanf(fp, "%d", &data[n + 800 * m]);
if you meant "\t" whcih is the tab character, it's not needed anyway and passing the value instead of it's address is Undefined Behavior, because fscanf() will treat the value as a pointer, and it's not likely pointing to a valid memory address, moreover, it's unintialized which is another reason for undefined behavior.
You declared data as char *data and store int's in it, that is also Undefined Behavior.
You must check the return value of fscanf() beacuse if it fails, then the value will be uninitialized and there will be once again, Undefined Behavior and also you are going to read past the end of the file because you will never know if you reached it.
You are writing into the file and you open it for reading, this
fprintf(fp, "\n");
is wrong, you don't need it to read from the file.
Don't cast the result of malloc() though this is not causing problems in this case, it will improve the quality of your code.
Don't use sizeof(char) it makes your code harder to read and it's completely unnecessary since the standard mandates that sizeof(char) == 1.
You don't need the nested loop to read the data, because the shape of the data is irrelevant since fscanf() ignores all whitespace characters.
It is sufficient to read throug the file and use a counter to move through the array, at the end you can check how many values where read to verify the integrity of the data.
This is a fixed version of your code
#include <stdio.h> /* printf, scanf, NULL */
#include <stdlib.h> /* malloc, free, rand */
int main()
{
FILE *fp;
size_t index;
int *data;
data = malloc(1280 * 800);
if (data == NULL)
{
printf("NOt able to allocate memory properly\n");
return 1;
}
fp = fopen("\\home\\studinstru\\Desktop\\filedump.txt", "r");
if (fp == NULL)
{
printf("Error in creating dump file\n");
free(data);
return 2;
}
while (fscanf(fp, "%d", &data[index]) == 1)
{
fprintf(stdout, "%d ", data[index]);
index += 1;
if (index % 800 == 0)
printf("\n");
}
fclose(fp);
return 0;
}
Note: I recommend the use of compiler warnings, they would help prevent silly mistakes and some other mistakes like char *data and reading int's into it.
Also, from your file path "\\home\\studinstru\\Desktop\\filedump.txt" it seems you are on a non-windows system, and very likely the directory separator is / instead of \, so the correct path has to be
"/home/studinstru/Desktop/filedump.txt"
Replace
fscanf(fp,"%d/t",data[m*800 + n]);
with
fscanf(fp,"%d/t",&data[m*800 + n]);
fscanf() needs address of destination variable as argument and not the variable itself.
Also I am not getting why are doing this:
fprintf(fp,"\n");
I'm working a program for a class and it's proving much more difficult than I thought.
It's my very first experience with C, but I've had some experience with Java so I understand the general concepts.
My goal: read in a text file that has some formatting requirements contained within the file, store the file in an array, apply the formatting and output the formatted text to stdout.
The problem: reading in the file is easy, but I'm having trouble with the formatting and output.
The challenge:
--the input file will begin with ?width X, ?mrgn Y, or both (where X and Y are integers). these will always appear at the beginning of the file, and will each be on a separate line.
--the output must have the text formatted as per the formatting request (width, margin).
--additionally, there is a 3rd format command, ?fmt on/off, which can appear multiple times at any point throughout the text and will turn formatting on/off.
--just a few catches: if no ?width command appears, formatting is considered off and any ?margin commands are ignored.
--if a ?width command appears, formatting is considered on.
--the files can contain whitespace (as both tabs and spaces) which must be eliminated, but only when formatting is on.
--dynamic memory allocation is not allowed.
Easy for a first C program right? My professor is such a sweety.
I've been working on this code for hours (yes, I know it doesn't look like it) and I'm making little progress so if you feel like a challenge I would very much appreciate help of any kind. Thanks!
So far my code reads in the text file and formats the margin correctly. Can't seem to find a good way to eliminate whitespace (I believe tokenizing is the way to go) or do the word wrap when the length of the line is longer than the ?width command.
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4
5 #define MAX_LINE_LEN 133 /* max 132 char per line plus one extra for the new line char
6 #define MAX_LINES 300 /* max 300 lines per input file */
7 #define MAX_CHARS 39900 /* max number of characters in the file */
8
9 /* Initializes array used to store lines read in from text
10 file as well as output array */
11 char input[MAX_LINE_LEN];
12 char buffer[MAX_CHARS];
13 char word_wrap[MAX_LINE_LEN];
14
15 /* Functions */
16 void parameters(char [], FILE *);
17
18 /* Variables */
19 int width = 0;
20 int margin = 0;
21
22 /*
23 argc is the count of input arguments
24 *argv is a pointer to the input arguments
25 */
26 int main (int argc, char *argv[])
27 {
28 /* Creates file pointer */
29 FILE *fp = fopen(argv[1], "r"); /* r for read */
30
31 if (!fp) /* Error checking */
32 {
33 printf("Error: Could not open file");
34 return 0;
35 }
36
37 /* Retrieves width and margin parameters from input file */
38 parameters(input, fp);
39
40 fclose(fp); /* Closes file stream */
41
42 return 0;
43 }
44
45 void parameters(char input[], FILE *fp)
46 {
47 /* Gets input file text line by line */
48 while (fgets (input, 133, fp) != NULL)
49 {
50 /* Creates a pointer to traverse array */
51 char *p = input;
52
53 /* Checks for width parameter read in from text file */
54 if (input[0] == '?' && input [1] == 'w')
55 {
56 strtok(input, " "); /* Eliminates first token '?width' */
57 width = atoi(strtok(NULL, " ")); /* Stores int value of ASCII token
58 p = NULL;
59 }
60
61 /* Checks for margin parameter read in from text file */
62 if (input[0] == '?' && input[1] == 'm')
63 {
64 strtok(input, " "); /* Eliminates first token '?mrgn' */
65 margin = atoi(strtok(NULL, " ")); /* Stores int value of ASCII token
66 p = NULL;
67 }
68
69 if (p != NULL) /* skips printing format tokens at beginning of file */
70 {
71 if (width == 0) /* no width command, formatting is off by default */
72 {
73 printf("%s", p); /* Prints unformatted line of text */
74 }
75 else /* formatting is on */
76 {
77 printf("%*s" "%s", margin, " ", p); /* Prints formatted line of text
78 }
79 }
80 }
81 }
82
And here's an example input file, along with its proper output:
?width 30
?mrgn 5
While there are enough characters here to
fill
at least one line, there is
plenty
of
white space which will cause
a bit of confusion to the reader, yet
the ?fmt off command means that
the original formatting of
the lines
must be preserved. In essence, the
command ?pgwdth is ignored.
Output:
While there are enough
characters here to fill
at least one line, there
is plenty of white space
which will cause a bit of
confusion to the reader,
yet the ?fmt off command means that
the original formatting of
the lines
must be preserved. In essence, the
command ?pgwdth is ignored.