Copying file and write the info of file backwards - c

Need create a copy of the file that was previously created with fifteen random numbers inside, and in this copy write those numbers backwards.
I tried to read the file with for() and write to the array, which will also fill in the newly created file with for(), but the IDE stops the script as soon as it goes to for().
#include <stdio.h>
#include <stdlib.h>
int main(){
char a[20], sf[20], tf[20];
FILE *source, *target;
int i;
printf("Enter name of file to copy\n");
gets(sf);
source = fopen(sf, "r");
if (source == NULL){
printf("Press any key to exit...\n");
exit(1);
}
printf("Enter name of target file\n");
gets(tf);
target = fopen(tf, "w");
if (target == NULL){
fclose(source);
printf("Press any key to exit...\n");
exit(1);
}
for(i=0;i<15;i++){
fscanf(source, "%d", a[i]);
//printf("%d\n", a[i]);
}
for(i=15;i>0;i--){
fprintf(target, "%d\n", a[i]);
}
//printf("File copied successfully.\n");
return 0;
}

Some remarks :
as it is said in remark you read int so you need an array of int, not an array of char to save them, currently you will write out of a with an undefined behavior
if you need to save 15 values an array for 15 is enough, 20 (supposing int) is useless
never use gets, it is deprecated (since years) because dangerous, use fgets to not take the risk to write out of the receiving string, and do not forget to remove the probable newline
may be the input and output files will be the same, so read first before to open output file and write its contents
fscanf(source, "%d", a[i]); is invalid and must be fscanf(source, "%d", &a[i]);
check the result of fscanf to manage error cases in the input file
fprintf(target, "%d\n", a[i]); must be fprintf(target, "%d\n", a[i-1]);
to explicitly fclose the output file is better in case you later transform your program to something more complex
A proposal :
#include <stdio.h>
#include <string.h>
#define N 15
FILE * openIt(const char * msg, const char * dir)
{
char fn[256];
printf(msg);
if (fgets(fn, sizeof(fn), stdin) == NULL)
/* EOF */
return NULL;
char * p = strchr(fn, '\n');
if (p != NULL)
*p = 0;
FILE * fp = fopen(fn, dir);
if (fp == NULL)
fprintf(stderr, "cannot open '%s'\n", fn);
return fp;
}
int main()
{
FILE * fp;
if ((fp = openIt("Enter name of file to copy\n", "r")) == NULL)
return -1;
int a[N], i;
for (i = 0; i != N; ++i) {
if (fscanf(fp, "%d", &a[i]) != 1) {
fprintf(stderr, "invalid integer rank %d\n", i);
fclose(fp);
return -1;
}
}
fclose(fp);
if ((fp = openIt("Enter name of target file\n", "w")) == NULL)
return -1;
while (i--) {
fprintf(fp, "%d\n", a[i]);
}
fclose(fp);
return 0;
}
Compilation and execution :
pi#raspberrypi:/tmp $ gcc -pedantic -Wall -Wextra r.c
pi#raspberrypi:/tmp $ cat in
1 2 3 4 5
6 7 8 9 10
11 12
13
14
15
not read
pi#raspberrypi:/tmp $ ./a.out
Enter name of file to copy
in
Enter name of target file
out
pi#raspberrypi:/tmp $ cat out
15
14
13
12
11
10
9
8
7
6
5
4
3
2
1
pi#raspberrypi:/tmp $ ./a.out
Enter name of file to copy
out
Enter name of target file
out
pi#raspberrypi:/tmp $ cat out
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
pi#raspberrypi:/tmp $

Related

Save just the second element of each line from a file into a vector in c

I have this function that saves in an integer variable all the numbers from a text file. But I want to make a change so that I can save just the second number in each line into a vector and then print the whole vector. Here is an example of the file.txt:
123 19
321 18
432 9
876 16
875 17
And here is the code that must be changed:
void LerVetor(int *V, int *N)
{
FILE *fp;
int marks;
fp = fopen("dados3.txt", "r");
if (fp == NULL)
printf("Falha ao abrir ficheiro\n");
rewind(fp);
do
{
fscanf(fp, "%d", &marks);
printf("%d\n", marks);
} while (!feof(fp));
fclose(fp);
}
The output is the same as the file.txt because the code just prints the content of the file.
Resume: Save just the second numbers of each line, ex: 19, 18, 9..., in a vector and then print the vector.
the following proposed code:
cleanly compiles
groups the variables with where they are used
properly checks and handles I/O errors
read/displays the second number from each line of the file
performs the desired functionality
and now, the proposed code:
#include <stdio.h>
#include <stdlib.h>
void LerVetor( void )
{
FILE *fp = fopen("dados3.txt", "r");
if( !fp )
{
perror("fopen to read: dados3.txt failed");
exit( EXIT_FAILURE );
}
int marks;
int dummy;
while( fscanf(fp, "%d %d", &dummy, &marks) == 2 )
{
printf("%d\n", marks);
}
fclose(fp);
}
One way you can do it is to pass a pointer to the vector (array of ints) where you need to store the values as a parameter of the function.
To dispose the first value in every line you can use a discard specifier %*d:
Live sample
#include <stdio.h>
void LerVetor(int* vector)
{
FILE *fp;
if (!(fp = fopen("dados3.txt", "r"))){
perror("Falha ao abrir ficheiro"); //print eventual open file error
return;
}
// keep reading lines discarding first value with %*d avoiding container overflow
for(int i = 0; fscanf(fp, "%*d %d", &vector[i]) == 1 && i < 100; i++)
printf("%d\n", vector[i]); //printing vector values
fclose(fp);
}
int main(void)
{
int vector[100];
LerVetor(vector);
return 0;
}

Search a element in file and print whole line

I have a file with these contents:
Code Name Income Allow Pens Ins Depend Charity Taxable Tax Net
------------------------------------------------------------------------------------------------------------------------
008 John 100000 4000 5000 1000 3200 1000 85800 20280 79720
001 Doe 50000 4000 0 500 1600 0 43900 7725 42275
I want to print a record if the input code is same as the code in the file.
This is my code:
fscanf(fp, " %3d%s%lf%lf%lf%lf%lf%lf%lf%lf%lf", &code_t, buffer, &inc_t, &personal, &pension_t, &health_t, &depend_t, &gift_t, &taxable_t, &tax_t, &net_t);
printf("\n");
printf(" 03d%20s%11.0lf%9.0lf%10.0lf%8.0lf%10.0lf%11.0lf%11.0lf%10.0lf%10.0lf\n", code_t, buffer, inc_t, personal, pension_t, health_t, depend_t, gift_t, taxable_t, tax_t, net_t);
`
but it doesn't work.
So I'm thinking about using fscanf to read only the code and then print the line which contains that code. But how can I read the code without other contents like Name, Income, ... and how to read if the code has leading 0 like that?
First you cannot read the file with its header using the scanf you give because Code is incompatible with the first %d, so you need to bypass the first 2 lines
Warning a % is missing in your printf to print the code, so the code is considered as the string by %s with an unspecified behavior (a crash generally)
But how can I read the code without other contents like Name, Income
Of course if you use your scanf you also read the other fields, is it a real problem ? You can also read line per line as a strings (fgets or getline) and look at the beginning if you have the expected code and in that case manage the rest of the string to extract the fields if needed etc
An other way if the content of the file is very formatted is to change the file pointer using fseek to only read the codes up to the expected one (see the proposal at the end of my answer).
how to read if the code has leading 0 like that?
I do not understand scanf read it well, this is not octal because there is 008. If the presence of the 0 at the left are important do not manage the code as a number but as a string both in the file and when the code to search is given
A code from yours reading well your input file :
#include <stdio.h>
int bypassLine(FILE * fp)
{
int c;
for (;;) {
c = fgetc(fp);
if (c == EOF)
return 0;
if (c == '\n')
return 1;
}
}
int main()
{
FILE * fp = stdin;
int code_t;
char buffer[64];
double inc_t, personal, pension_t, health_t, depend_t, gift_t, taxable_t, tax_t, net_t;
if (!bypassLine(fp) || !bypassLine(fp))
puts("too short file");
else {
while (fscanf(fp, " %3d%s%lf%lf%lf%lf%lf%lf%lf%lf%lf", &code_t, buffer, &inc_t, &personal, &pension_t, &health_t, &depend_t, &gift_t, &taxable_t, &tax_t, &net_t) == 11) {
printf(" %03d%20s%11.0lf%9.0lf%10.0lf%8.0lf%10.0lf%11.0lf%11.0lf%10.0lf%10.0lf\n", code_t, buffer, inc_t, personal, pension_t, health_t, depend_t, gift_t, taxable_t, tax_t, net_t);
}
}
}
Compilation and execution :
pi#raspberrypi:/tmp $ gcc -pedantic -Wextra f.c
pi#raspberrypi:/tmp $ cat f
Code Name Income Allow Pens Ins Depend Charity Taxable Tax Net
------------------------------------------------------------------------------------------------------------------------
008 John 100000 4000 5000 1000 3200 1000 85800 20280 79720
001 Doe 50000 4000 0 500 1600 0 43900 7725 42275
pi#raspberrypi:/tmp $ ./a.out < f
008 John 100000 4000 5000 1000 3200 1000 85800 20280 79720
001 Doe 50000 4000 0 500 1600 0 43900 7725 42275
pi#raspberrypi:/tmp $
Note there is no protection against an overflow when reading the string in scanf with just %s, if is better to use %63s because I sized buffer 64
A little change to search for the code, still using your scanf, giving the name of the file and the expected code in argument :
#include <stdio.h>
int bypassLine(FILE * fp)
{
int c;
for (;;) {
c = fgetc(fp);
if (c == EOF)
return 0;
if (c == '\n')
return 1;
}
}
int main(int argc, char ** argv)
{
if (argc != 3)
printf("usage : %s <file> <code>\n", *argv);
else {
FILE * fp;
int code_t, expected;
char buffer[64];
double inc_t, personal, pension_t, health_t, depend_t, gift_t, taxable_t, tax_t, net_t;
if ((fp = fopen(argv[1], "r")) == NULL) {
fprintf(stderr, "cannot open '%f'\n", argv[1]);
return -1;
}
if (!bypassLine(fp) || !bypassLine(fp)) {
fprintf(stderr, "too short file '%s'\n", argv[1]);
fclose(fp);
return -1;
}
if (sscanf(argv[2], "%d%c", &expected, buffer) != 1) {
fprintf(stderr, "invalid code '%s'\n", argv[2]);
}
else {
while (fscanf(fp, " %3d%63s%lf%lf%lf%lf%lf%lf%lf%lf%lf", &code_t, buffer, &inc_t, &personal, &pension_t, &health_t, &depend_t, &gift_t, &taxable_t, &tax_t, &net_t) == 11) {
if (code_t == expected) {
printf(" %03d%20s%11.0lf%9.0lf%10.0lf%8.0lf%10.0lf%11.0lf%11.0lf%10.0lf%10.0lf\n", code_t, buffer, inc_t, personal, pension_t, health_t, depend_t, gift_t, taxable_t, tax_t, net_t);
fclose(fp);
return 0;
}
}
fprintf(stderr, "code %d not found in '%s'\n", expected, argv[1]);
}
fclose(fp);
return -1;
}
}
Compilation and execution :
pi#raspberrypi:/tmp $ gcc -pedantic -Wextra f.c
pi#raspberrypi:/tmp $ ./a.out ./f 2
code 2 not found in './f'
pi#raspberrypi:/tmp $ ./a.out ./f 8
008 John 100000 4000 5000 1000 3200 1000 85800 20280 79720
pi#raspberrypi:/tmp $
An other way using fseek to move directly from code to code in the file :
#include <stdio.h>
int bypassLine(FILE * fp)
{
int c;
for (;;) {
c = fgetc(fp);
if (c == EOF)
return 0;
if (c == '\n')
return 1;
}
}
int main(int argc, char ** argv)
{
if (argc != 3)
printf("usage : %s <file> <code>\n", *argv);
else {
FILE * fp;
int code_t, expected;
char buffer[64];
double inc_t, personal, pension_t, health_t, depend_t, gift_t, taxable_t, tax_t, net_t;
if ((fp = fopen(argv[1], "r")) == NULL) {
fprintf(stderr, "cannot open '%f'\n", argv[1]);
return -1;
}
if (!bypassLine(fp) || !bypassLine(fp)) {
fprintf(stderr, "too short file '%s'\n", argv[1]);
fclose(fp);
return -1;
}
if (sscanf(argv[2], "%d%c", &expected, buffer) != 1) {
fprintf(stderr, "invalid code '%s'\n", argv[2]);
}
else {
long offset = ftell(fp);
while (fscanf(fp, " %03d", &code_t) == 1) {
if (code_t == expected) {
/* extract the other fields */
if (fscanf(fp, "%63s%lf%lf%lf%lf%lf%lf%lf%lf%lf", buffer, &inc_t, &personal, &pension_t, &health_t, &depend_t, &gift_t, &taxable_t, &tax_t, &net_t) == 10) {
printf(" %03d%20s%11.0lf%9.0lf%10.0lf%8.0lf%10.0lf%11.0lf%11.0lf%10.0lf%10.0lf\n", code_t, buffer, inc_t, personal, pension_t, health_t, depend_t, gift_t, taxable_t, tax_t, net_t);
fclose(fp);
return 0;
}
else {
fprintf(stderr, "code %d found but cannot read next fields\n", code_t);
fclose(fp);
return -1;
}
}
/* the lines are supposed having all the times 114 characters newline included */
offset += 114;
if (fseek(fp, offset, SEEK_SET) == -1) {
fprintf(stderr, "error when going at offset %d of '%s'\n", offset, argv[1]);
fclose(fp);
return -1;
}
}
fprintf(stderr, "code %d not found in '%s'\n", expected, argv[1]);
}
fclose(fp);
return -1;
}
}
Compilation and execution :
pi#raspberrypi:/tmp $ gcc -pedantic -Wextra f.c
pi#raspberrypi:/tmp $ cat f
Code Name Income Allow Pens Ins Depend Charity Taxable Tax Net
------------------------------------------------------------------------------------------------------------------------
008 John 100000 4000 5000 1000 3200 1000 85800 20280 79720
001 Doe 50000 4000 0 500 1600 0 43900 7725 42275
pi#raspberrypi:/tmp $ ./a.out ./f 8
008 John 100000 4000 5000 1000 3200 1000 85800 20280 79720
pi#raspberrypi:/tmp $ ./a.out ./f 1
001 Doe 50000 4000 0 500 1600 0 43900 7725 42275
pi#raspberrypi:/tmp $ ./a.out ./f 11
code 11 not found in './f'
I want to print a record if the input code is same as the code in the file.
If your goal is simply to print the records (aka lines) where "Code" matches some value given by the user, your approach seems a bit too complex as there is no need for scanning all the fields.
Simply use fgets to read the line, then check the Code value and do the print if it matches.
Something like:
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
int main(int argc, char* argv[]){
if (argc != 2)
{
printf("Wrong usage...\n");
return 1;
}
int code_to_print = atoi(argv[1]);
int code_read;
FILE* fp = fopen("db.txt", "r");
if (!fp)
{
printf("File error...\n");
return 1;
}
char buf[1024];
while (fgets(buf, sizeof buf, fp))
{
if (sscanf(buf, "%d", &code_read) == 1 && code_read == code_to_print)
{
printf("%s", buf);
}
}
fclose(fp);
}
Use the program like:
./prog 8
.. how to read if the code has leading 0 like that?
If the leading zeros are important then you can't scan using %d as that will "remove" the zeros. Instead you need to scan the Code as a word. Like:
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
int main(int argc, char* argv[]){
if (argc != 2)
{
printf("Wrong usage...\n");
return 1;
}
char code_read[4] = {0};
FILE* fp = fopen("db.txt", "r");
char buf[1024];
while (fgets(buf, sizeof buf, fp))
{
if (sscanf(buf, "%3s", code_read) == 1 && strcmp(code_read, argv[1]) == 0)
{
printf("%s", buf);
}
}
fclose(fp);
}
Use the program like:
./prog 008

Reading a file and then sorting it into 10 columns

I'm looking to sort a txt file that contains 1199 numbers in 10 columns per row, and I know that the last row will have 10 or fewer columns.
However, I'm getting 11 columns on the first row.
Thanks for the help.
#include <stdio.h>
#define t 1024
int main()
{
int i=0, c;
char p[t];
FILE *f;
f = fopen("CMB.txt", "r");
while ((c = getc(f)) != EOF)
{
fscanf(f, "%s", p);
if(i%10 == 0 && i > 0)
{
printf("\n");
}
printf("%s ", p);
if (c == '\n')
{
i++;
}
}
printf("\n %d", i+1);
fclose(f);
}
When I try your code it prints correctly the 10 columns you are expecting , perhaps you didn't recompile after modifying.
This is your code , I only removed the file reading and printing char.
#include <stdio.h>
int main()
{
int i=0;
//, c;
// char p[t];
// FILE *f;
// f = fopen("CMB.txt", "r");
while (i<30)
{
// fscanf(f, "%s", p);
if(i%10 == 0 && i > 0)
{
printf("\n");
}
printf("%d ", i);
// if (c == '\n')
// {
i++;
// }
}
// printf("\n %d", i+1);
// fclose(f);
}
Continuing from my earlier comment, when reading columns of data from a text file, it is generally better to read a line of input at a time with a line-oriented input function such as fgets or POSIX getline and then to parse the data from the buffer filled with sscanf (or walking a pointer down the buffer picking out what you need)
In your case when dealing with a fixed number of columns (10) where less than all values may be present, sscanf provides a way to determine exactly how many values are present in each row while allowing you to make use of the data if less than 10 are present.
sscanf (as with all scanf functions) returns the number of successful conversions took place based on the format string you provide (or returning EOF if the end of input is encountered before a conversion takes place). If you want to read 10-integer values from each line of data into an integer array names arr, you could use fgets to read the line into a buffer (say buf) and then separate the integer values head in buf with sscanf, e.g.
...
while (fgets (buf, MAXC, fp)) { /* read each line into buf */
/* parse into integer values with sscanf saving return */
int rtn = sscanf (buf, "%d %d %d %d %d %d %d %d %d %d",
&arr[0], &arr[1], &arr[2], &arr[3], &arr[4],
&arr[5], &arr[6], &arr[7], &arr[8], &arr[9]);
...
Then you simply validate the return (rtn) using whatever if..else or switch... statements you need. Here we can simply sum the number of values read and output the row number for any row containing less than COL number of values for purposes of this example, e.g.
...
if (rtn > 0) /* did at least one conversion take place? */
n += rtn; /* increment count of values read */
if (rtn < COL) /* were less than COL values read? */
printf ("row[%zu]: %d values read.\n", row + 1, rtn);
row++; /* increment row count */
}
Putting it altogether, you could do something like the following:
#include <stdio.h>
#define COL 10
#define MAXC 1024
int main (int argc, char **argv) {
char buf[MAXC];
int arr[COL] = {0};
size_t n = 0, row = 0;
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
while (fgets (buf, MAXC, fp)) { /* read each line into buf */
/* parse into integer values with sscanf saving return */
int rtn = sscanf (buf, "%d %d %d %d %d %d %d %d %d %d",
&arr[0], &arr[1], &arr[2], &arr[3], &arr[4],
&arr[5], &arr[6], &arr[7], &arr[8], &arr[9]);
if (rtn > 0) /* did at least one conversion take place? */
n += rtn; /* increment count of values read */
if (rtn < COL) /* were less than COL values read? */
printf ("row[%zu]: %d values read.\n", row + 1, rtn);
row++; /* increment row count */
}
if (fp != stdin) fclose (fp); /* close file if not stdin */
printf ("%zu values read from file.\n", n);
}
Example Input File
Reading a data file with 10-integers per-row for 119 rows and reading a final row with 9-integers as you describe in your question, you could use an input file like:
$ head -n4 dat/1199_10col.txt; echo "<snip>"; tail -n4 dat/1199_10col.txt
1 2 3 4 5 6 7 8 9 10
11 12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29 30
31 32 33 34 35 36 37 38 39 40
<snip>
1161 1162 1163 1164 1165 1166 1167 1168 1169 1170
1171 1172 1173 1174 1175 1176 1177 1178 1179 1180
1181 1182 1183 1184 1185 1186 1187 1188 1189 1190
1191 1192 1193 1194 1195 1196 1197 1198 1199
Example Use/Output
Running the code against the above file would yield the expected results of reading 1199 values, 10-integers per-row with 9-integers read from the final row with notice of the short row:
$ ./bin/read10col <dat/1199_10col.txt
row[120]: 9 values read.
1199 values read from file.
While there are many ways to do this, and arguably using fgets with strtol provides opportunity for finer grained error detection, this is probably one of the more simple and straight-forward approaches.
Look things over and let me know if you have further questions.
Why do you read a character before the first number? Why do you only increment i if this character is a newline?
If the file contains just numbers, you can simplify the code this way:
#include <stdio.h>
int main() {
int i, n;
FILE *f = fopen("CMB.txt", "r");
if (f != NULL) {
for (i = 0; fscanf(f, "%d", &n) == 1; i++) {
/* output the number followed by a tab, or by a newline every 10 numbers */
printf("%d%c", n, "\t\n"[i % 10 == 9]);
}
if (i % 10 != 0) {
printf("\n");
}
fclose(f);
}
return 0;
}
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE * fp;
char *line;
int i;
size_t len = 0;
fp = fopen("CMB.txt", "r");
while (getline(&line, &len, fp) != -1)
{
fscanf(fp, "%s", line);
if(i%10 == 0 && i > 0)
{
printf("\n");
}
printf("%s\t ", line);
i++;
}
printf("\n\n%d", i);
fclose(fp);
return 0;
}
So now the numbers from the file are sorted in 10 columns, but the last line only have 8 columns when it should have 9. When I count (i) to see how many lines the while loop reads it only reads 1198, but i should read 1199. So I'm guessing it's skipping the first line? Appreciate the help :D

fscanf returns 3 instead of -1 (EOF) at the end of the file

So there's a file I'm using fscanf() in. I've set a condition in my code that when (fscanf(...) == EOF, the program needs to break out of the function I'm currently in. The thing is, this condition is never satisfied in any of the cases where there's no more lines of text in the file. EOF is always -1, whereas fscanf(...) returns 4 each time there's a line of code, and 3 when there's nothing left for it to search through (instead of -1). If I add a line of code similar to the other ones, I will simply get one more instance of fscanf() returning 4, and then again, it'll give me a 3.
What could possibly be the issue? Thank you in advance!
Sample text file content:
CHRISTOU GIORGOS,140,VAS. OLGAS 112
MALAKOU MALAKOS,150,DRAS. BAGAS 12
TSIKOU GIJRAN,140,JABS. DRALGAS 1
TSIKOU BIRBAN,140,JABS. DRALGAS 1
DELHDHMHTRIOU SPYROS,50,SPEED. BAGAS 62
FOX SIN,40,BAN. NINJA 1
Code:
#include <stdio.h>
#define M 100
typedef struct {
char name[30];
int apousies;
} studentT;
void readInput (FILE* infile, studentT students[], int *pApousies, int *pStudents);
int main()
{
char inputfilename[30];
FILE* infile;
while (1) {
printf("Input file name :");
gets(inputfilename);
infile = fopen(inputfilename, "r");
if (infile != NULL) break;
printf("Cannot open input file %s. Try again.\n", inputfilename);
}
studentT students[M];
int numberOfStudents = 0, numberOfApousies = 0;
readInput(infile, students, &numberOfApousies, &numberOfStudents);
fclose(infile);
return 0;
}
void readInput (FILE* infile, studentT students[], int *pApousies, int *pStudents)
{
int nscan, apousies, studcount, apouscount, line;
char name[30], comments[68], termch;
line = 0;
while (1)
{
nscan = fscanf(infile, "%30[^,], %d, %68[^\n]%c", name, &apousies, comments, &termch);
/* printf("onoma: %s apousies: %d sxolia: %s terma: %c\n", name, apousies, comments, termch);
printf("%d\n", nscan);
printf("%d\n", EOF);*/
if (nscan == EOF) break;
line++;
if (nscan != 4 || termch != '\n')
{
printf("Error in line %d. Program termination\n", line);
exit(1);
}
}
}
fscanf returns 3 instead of -1 (EOF) at the end of the file
Because the last line lacks a '\n'.
OP's code "works" with the "tmp.txt" the below code makes.
fscanf() is hard to use right. Easier to code and debug with fgets(). Discussion follows.
"%30[^,]" allows too much for char name[30]. Use char name[30+1] or "%29[^,]"
OP's approach can readily fail with seemingly minor parsing problems such as a missing '\n' on the last line. After such a failure, recovery is extraordinary difficult with fscanf()
Debug: Importantly, the below print should not be attempted until code insures nscan >= 4
if (nscan >= 4) // add
printf("onoma: %s apousies: %d sxolia: %s terma: %c\n", name, apousies, comments, termch);
Instead, use fgets(). With line orientated data, this really is the best first step.
fscanf() is challenging to use and cope with errors. Far simpler to read a line with fgets() and then parse.
Using " %n" is a nice way to detect if all the line parsed.
#include <stdio.h>
#include <stdlib.h>
#define M 100
typedef struct {
char name[30];
int apousies;
} studentT;
void readInput(FILE* infile, studentT students[], int *pApousies,
int *pStudents) {
(void) students;
(void) pApousies;
(void) pStudents;
int line = 0;
char buf[200];
while (fgets(buf, sizeof buf, infile)) {
int apousies;
char name[30], comments[68];
int n = 0;
line++;
sscanf(buf, " %29[^,],%d , %67[^\n] %n", name, &apousies, comments, &n);
if (n == 0 || buf[n]) {
fprintf(stderr, "Error in line %d <%s>. Program termination\n", line, buf);
exit(1);
}
printf("Success %d <%s> %d <%s>\n", line, name, apousies, comments);
}
}
Sample use
int main() {
FILE *f = fopen("tmp.txt", "w");
fputs("CHRISTOU GIORGOS,140,VAS. OLGAS 112\n"
"MALAKOU MALAKOS,150,DRAS. BAGAS 12\n"
"TSIKOU GIJRAN,140,JABS. DRALGAS 1\n"
"TSIKOU BIRBAN,140,JABS. DRALGAS 1\n"
"DELHDHMHTRIOU SPYROS,50,SPEED. BAGAS 62\n"
"FOX SIN,40,BAN. NINJA 1\n", f);
fclose(f);
f = fopen("tmp.txt", "r");
studentT st[M];
readInput(f, st, NULL, NULL);
fclose(f);
}
Output
Success 1 <CHRISTOU GIORGOS> 140 <VAS. OLGAS 112>
Success 2 <MALAKOU MALAKOS> 150 <DRAS. BAGAS 12>
Success 3 <TSIKOU GIJRAN> 140 <JABS. DRALGAS 1>
Success 4 <TSIKOU BIRBAN> 140 <JABS. DRALGAS 1>
Success 5 <DELHDHMHTRIOU SPYROS> 50 <SPEED. BAGAS 62>
Success 6 <FOX SIN> 40 <BAN. NINJA 1>

Read till end of file into array

I've been trying to figure where I'm going wrong but I can't seem to point out where my error is exactly.
I'm trying to read from my text file, these integers
5 2 4 9 10 1 8 13 12 6 3 7 11
into an array A. To make sure it works, I was trying to print A but only getting large random numbers instead. Can someone help me see where i'm going wrong please?
int main(){
FILE* in = fopen("input.txt","r");
int A[100];
while(!feof(in)){
fscanf(in, "%s", &A);
printf("%d", A)
}
fclose(in);
return 0;
}
*this is just the main parts of the code related to the question
For all those who actually read why using feof is always wrong, the solution is something similar to the following. The code will open the filename given as the first argument to the program (or read from stdin by default):
#include <stdio.h>
enum { MAXI = 100 };
int main (int argc, char **argv) {
int i = 0, A[MAXI] = {0}; /* initialize variables */
/* read from file specified as argument 1 (or stdin, default) */
FILE *in = argc > 1 ? fopen (argv[1],"r") : stdin;
if (!in) { /* validate file opened for reading */
fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
return 1;
}
/* read each number from file or until array full */
while (i < MAXI && fscanf (in, " %d", &A[i]) == 1)
printf (" %d", A[i++]);
putchar ('\n');
if (in != stdin) fclose (in);
printf ("\n '%d' numbers read from the file.\n\n", i);
return 0;
}
Example Use/Output
Using your example values in the file dat/myints.txt results in the following:
$ ./bin/rdints dat/myints.txt
5 2 4 9 10 1 8 13 12 6 3 7 11
'13' numbers read from the file.

Resources