c fscanf using and new line - c

I need to receive and put into variables text file.
For example:
/*
system_1
6
challenge_2 22 2
challenge_3 33 3
challenge_4 44 1
challenge_5 55 3
challenge_6 66 3
challenge_1 11 1
4
room_2 1 22
room_1 3 11 44 66
room_3 3 55 33 11
room_4 4 22 44 55 66
*/
I know that every one of the words (not line) is not more than 50 characters.
What will be the easy way to put each word in the appropriate (int,string...).
Also I need to know where the line is ending because the number of words in line is not constant.
I think fscanf is the most efficient, but I dont know how to use it for line ending and such...
I would love to see an example of using fscanf as I wanted.
Thanks in advance.

It's more efficient, because you do not know the format string to use fgets to return a line from the file, then to parse it yourself rather than using scanf.
An example would be like this:
FILE* file = fopen("somefile.txt", "r");
char buffer[51];
while (fgets(buffer, 50, file)) {
// Buffer now stores the line, lets see if it can be an integer.
int possible_num = 0;
// sscanf will return 1 if it read a possible integer from the buffer.
if (sscanf(buffer, "%d", &possible_num) == 1) {
// We read a number, so possible_num is now the number.
}
else {
// We read a string, buffer stores the string.
}
}
NOTE: The code will return a false positive if your string is something like "10hello", as sscanf will still read the 10. There are multiple ways of checking if a string is a valid integer out there in C, which I'm sure you will be able to find on StackOverflow, but this code should give you a place to get started.

Related

Input in C, special case?

Good day,
I've got the following code:
43 while (TRUE)
44 {
45 printf("Swipe Card: ");
46 scanf("%s;%s=%s", id, banner, cp);
47 printf("%s\n%s\n%s\n", id, banner, cp);
48 ProcessStudent(banner, file);
49
50 }
I've dynamically allocated id, banner, and cp, however when I try to print them (which I did just to check their contents) everything is taken into 'id' only. The string I'm trying to read looks like this %GRE068?;01540594=000331!
scanf doesn't try to do a full pattern match of the format string. %s input format simply reads everything up to the next whitespace (or EOF). After that, it looks for a ;, and since it doesn't find that it doesn't parse any of the other inputs.
If you want to stop at some other character, use [^char]
scanf("[^;];%[^=]=%s", id, banner, cp);

C reading file using ./a.out<filename and how to stop reading

In my class today we were assigned a project that involves reading in a file using the ./a.out"<"filename command. The contents of the file look like this
16915 46.25 32 32
10492 34.05 56 52
10027 98.53 94 44
13926 32.94 19 65
15736 87.67 5 1
16429 31.00 58 25
15123 49.93 65 38
19802 37.89 10 20
-1
but larger
My issue is that any scanf used afterwards is completely ignored and just scans in what looks like garbage when printed out, rather than taking in user input. In my actual program this is causing an issue with a menu that requires input.
How do I get the program to stop reading the file provided by the ./a.out"<"filename command?
also I stop searching at -1 rather than EOF for the sake of not having an extra set of array data starting with -1
ex
-1 0 0 0
in my real program the class size is a constant that is adjustable and is used to calculate class averages, I'd rather not have a set of 0's skewing that data.
#include <stdio.h>
int main(void)
{
int i = 0,j = 1,d,euid[200],num;
int tester = 0;
float hw[200],ex1[200],ex2[200];
while(j)
{
scanf("%d",&tester);
if( tester == -1)
{
j = 0;
}
else
{
euid[i] = tester;
}
scanf("%f",hw+i);
scanf("%f",ex1+i);
scanf("%f",ex2+i);
i++;
}
for(d = 0;d < 50;d++) /*50 because the actual file size contains much more than example*/
{
printf("euid = %d\n",euid[d]);
printf("hw = %f\n",hw[d]);
printf("ex1 = %f\n",ex1[d]);
printf("ex2 = %f\n",ex2[d]);
}
printf("input something user\n");
scanf("%d",&num);
printf("This is what is being printed out -> %d\n",num);
return 0;
}
I'm having the exact same problem. Tried every method I could find to eat the remaining input in the buffer, but it never ends.
Got it to work using fopen and fscanf, but the prof. said he prefers the code using a.out < filename
Turns out this is in fact not possible.

Use fscanf to read two lines of integers

I want to ask something that I write in C.
I use the fopen() command to open and read a text file that contains only two lines. in
first line is an integer N number, and in the second line is the N integer numbers that the first line says.
Eg.
-------------- nubmers.txt --------------
8 <-- we want 8 numbers for the 2nd line
16 8 96 46 8 213 5 16 <-- and we have 8 numbers! :)
but I want to take restrictions when the file openend.
the number N should be between 1 ≤ Ν ≤ 1.000.000. If not then show an error message. If the file is ok then the programm continue to run with another code.
Here is what I done until now:
int num;
....
fscanf(fp,"%d",&num); // here goes the fscanf() command
if(num<1 || num>1000000) // set restrictions to integer
{
printf("The number must be 1<= N <= 1.000.000",strerror(errno)); // error with the integer number
getchar(); // wait the user press a key
return 0; // returning an int of 0, exit the program
}
else // if everything works.....
{
printf("work until now"); // Everything works until now! :)
getchar(); // wait the user press a key
return 0; // returning an int of 0, exit the program
}
But the problem is that the restriction checks only for the first line number , it's correct though, but don't read the numbers in the second line.
What I mean is that :
Lets say that I have the number 10 in the first line.
The code will analyze the number, will check for restrictions and will proceed to the 'else' part
else // if everything works.....
{
printf("work until now"); // Everything works until now! :)
getchar(); // wait the user press a key
return 0; // returning an int of 0, exit the program
}
..and it will said that everything is working.
But what if I have 20 numbers in the second line? -when I need only 10
Eg.
-------------- nubmers.txt --------------
10
16 8 96 46 8 213 5 16 8 9 21 5 69 64 58 10 1 7 3 6
So I hoped be as cleared as I could. My question is that I need a code in the program, besides the 1st restriction, that have also another one restriction under the first that will read the second line of the txt file with the numbers and check if there are as many numbers as the first line says!
How do I do that?
If you guys want any other declarations feel free to ask!
Hope I was clear with my problem :)
This will check the number of integers and report too many or not enough. The integers are not saved except for each one being read into the value. Do you want to store each integer?
fscanf(fp,"%d",&num); // here goes the fscanf() command
if(num<1 || num>1000000) // set restrictions to integer
{
printf("The number must be 1<= N <= 1.000.000",strerror(errno)); // error with the integer number
getchar(); // wait the user press a key
return 0; // returning an int of 0, exit the program
}
else // if everything works.....
{
int i = 0;
int value = 0;
while ( fscanf ( fp, "%d", &value) == 1) { // read one integer
i++; // this loop will continue until EOF or non-integer input
}
if ( i > num) {
printf ( "too many integers\n");
}
if ( i < num) {
printf ( "not enough integers\n");
}
getchar(); // wait the user press a key
return 0; // returning an int of 0, exit the program
}
use a loop that takes the first num and checks is is the number of integers in next line:
int z = num;
while(z--){
if (getchar() == EOF)
printf("err")
}
Do it like this:
fscanf(fp,"%d",&num);
// next lines of code (restrictions). Then place the below code before getchar in the else
int temp[num+1];// space to store num integers to temp and 1 space to check for extra number
for(i=0;i<num;i++)
{
if(fscanf(fp,"%d",&temp[i]) != 1)// fscanf will automatically read 2nd line and store them in temp array
//error ! Less numbers in file !
}
if(fscanf(fp,"%d",&temp[num]==1) //if still numbers can be scanned
//Extra numbers found in line 2

C: Write to a specific line in the text file without searching

Hello I have file with text:
14
5 4
45 854
14
4
47 5
I need to write a text to a specific line. For example to the line number 4 (Doesn't matter whether I will append the text or rewrite the whole line):
14
5 4
45 854
14 new_text
4
47 5
I have found function fseek(). But in the documentation is written
fseek(file pointer,offset, position);
"Offset specifies the number of positions (bytes) to be moved from the location specified bt the position."
But I do not know the number of bites. I only know the number of lines. How to do that? Thank you
You can't do that, (text) files are not line-addressable.
Also, you can't insert data in the middle of a file.
The best way is to "spool" to a new file, i.e. read the input line by line, and write that to a new file which is the output. You can then easily keep track of which line you're on, and do whatever you want.
I will assume that you are going to be doing this many times for a single file, as such you would be better indexing the position of each newline char, for example you could use a function like this:
long *LinePosFind(int FileDes)
{
long * LinePosArr = malloc(500 * sizeof(long));
char TmpChar;
long LinesRead = 0;
long CharsRead = 0;
while(1 == read(FileDes, &TmpChar, 1))
{
if (!(LinesRead % 500)
{
LinePosArr = realloc(LinePosArr, (LinesRead + 500) * sizeof(long));
}
if (TmpChar == '\n')
{
LinePosArr[LinesRead++] = CharsRead;
}
CharsRead++;
}
return LinePosArr;
}
Then you can save the index of all the newlines for repeated use.
After this you can use it like so:
long *LineIndex = LinePosFind(FileDes);
long FourthLine = LineIndex[3];
Note I have not checked this code, just written from my head so it may need fixes, also, you should add some error checking for the malloc and read and realloc if you are using the code in production.

How do you read in a number and a string from a file in C? Keeping in mind that some lines in the file only has a number and not a string

I have a file with multiple lines, and on each line there is a number followed by a space and then a string. But some lines in the file do not have a string following the digit. Here is part of the file:
10
17
38 So You Want to Be a Rock 'N' Roll Star
22 Have You Seen Her Face
12 C.T.A. - 102
16 Renaissance Fair
12 Time Between
23 Everybody's Been Burned
18 Thoughts and Words
12 Mind Gardens
13 My Back Pages
21 The Girl with No Name
3 Why
19 It Happens Each Day
16 Don't Make Waves
13 My Back Pages
12 Mind Gardens
11 Lady Friend
18 Old John Robertson
19
13 Ice Cream Man
14 Hang on Sloopy
Here is what i have so far:
#include <stdio.h>
typedef struct
{
int num_tracks;
char tracks[];
}album_store;
int main(int argc, char *argv[])
{
album_store album[10000];
int numb_tracks;
char line;
int i=0;
if (argc <2 )
{
printf("You need at least one argument\n");
}
else
{
FILE *file;
file=fopen(argv[1],"r");
while(fscanf(file,"%d %[^\n]",&numb_tracks,album[i].tracks) != EOF)
{
album[i].num_tracks=numb_tracks;
printf("%d %s\n",album[i].num_tracks,album[i].tracks);
i++;
}
}
}
Now my code reads in the lines, but not the spaces. Or rather it does not know how to detect if a line does not have a string after the digit. The output of my code looks like:
10 17
38 So You Want to Be a Rock 'N' Roll Star
22 Have You Seen Her Face
12 C.T.A. - 102
16 Renaissance Fair
12 Time Between
23 Everybody's Been Burned
18 Thoughts and Words
12 Mind Gardens
13 My Back Pages
21 The Girl with No Name
3 Why
19 It Happens Each Day
16 Don't Make Waves
13 My Back Pages
12 Mind Gardens
11 Lady Friend
18 Old John Robertson
19 13 Ice Cream Man
My question is how do i get the output of my code to match the input from the file? What would i have to change in my code? Any help is greatly appreciated!
You can't (reasonably) use fscanf() unless you know that all your lines are exactly the same correct format. Instead, I would suggest using fgets() to get one line of text at a time, then parse that line (perhaps using sscanf()).
For example,
char buf[1000];
while (fgets(buf, sizeof(buf), file) != NULL) {
sscanf(buf,"%d %[^\n]",&numb_tracks,album[i].tracks);
// etc
}
You'll want to add checking of the return value of sscanf() to the above sample.

Resources