read from text file and put into struct - c

i have assembler file actually text file like that
1 # Test case 1 for assembler
2
3 .text
4 test1: lwa $1,val1
5 prh $1
6 val12: lwa $2,val2
7 prh $2
..................
i am reading each line with fgets and keeping in char buffer which name is "linebuffer"
and im reading linebuffer with sscanf.
while((fgets(linebuffer,sizeof(linebuffer),ifp)!=NULL)
{
sscanf(linebuffer,"%s%s%s%s",line[i].label,line[i].opcode,line[i].operands,line[i].comment);
......
}
and i want keep them into struct,
struct instrucion{
char lable[8];
char opcode[4];
char opearand[15];
char comment[100];
}line[65536];
problem is some columns doesnt have anything just space and sscanf skipping spaces and reading very next string and keeping in first column. sorry i could not understand exactly but i hope somebody is understand.
for example i want like that for 3rd line;
line[2].label=NULL
line[2].opcode=".text"
line[2].opernds=NULL
line[2].comment=NULL
for 4th line;
line[3].label="test1:"
line[3].opcode="lwa"
line[3].operands="$1,val1"
line[3].comment=NULL
problem is starting with 5th line its has to be like that
line[4].label=NULL
line[4].opcode="prh"
line[4].operands="$1"
line[4].comment=NULL
buts when i run code im getting this result;
line[4].label="prh"
line[4].opcode="$1"
line[4].opernds=NULL
line[4].comment=NULL
how can i deliminate this linebuffer correctly?

OK, so your first problem is that fgets() does not read one line - It reads up to sizeof(linebuffer) number of bytes, you can see it's man page here:
http://linux.die.net/man/3/gets
Second, say that you do have only one line in the string "linebuffer", what you would like to do is use sscanf return value to determine which tokens appear in the line (scanf functions family return the number of parameters that were read from the stream).
Third, pay attention to the fact the scanf considers only spaces and newlines as tokens separators, so it will not separate the string "$1,val1" to the two sub-strings - you will need to do it manually.
And finally, there's a string-parsing function that can maybe make you life easier- strtok_r. You can see it's man page here:
http://linux.die.net/man/3/strtok_r
Amnon.

Related

How to find out how many words are in each line?

Say you have a text file filled with sentences. For example:
hey how are you
you good?
nice to meet you jeff
I'm writing a program to print things out depending on how many indexes are on each line but I cant wrap my head around how to find how many words on each line. How could I go about counting how many words are on each line?
for (int i=0; i < wordle->leng; i++) {
printf ("%s ", wordle->allwords[i]);
This is my print function for the program. leng is how many lines so it knows how many times to repeat.
Some of the lines have 5 words, some 3, and it isn't printing in the correct format. Also not all lines will end with punctuation.
The POSIX getline() function is very useful for that; it reads line from stream until EOL. So you can read with that line by line and the you could make a loop that adds 1 to int word_count = 0; every time you read something that is not a whitespace and the previous char before that was whitespace (but you have to make additional logic for initial word).
You can use fgets() if you don't have getline() available, but it doesn't expand the buffer to deal with extra long lines, unlike getline().

How to slice/index data in c

I am trying to learn C and have recieved a homework assignment to write code which can read data from a .txt file and print out particular lines.
I wrote the following:
#include <stdio.h>
void main() {
char str[5];
FILE *fp;
fp=fopen("data.txt","r");
int i;
for (i=1;i<=5;i++){
fgets(str,5,fp);
printf("%d \n",i);
if (i==1||i==3||i==5) {
printf("%s \n \n",str);
}
}
}
The file data.txt is just the following:
3.21
5.22
4.67
2.31
2.51
1.11
I had read that each time fgets is run, the pointer is updated to point to the next line. I thought I could keep running fgets and then only print the string str when at the correct value for i (the line I want output on the console).
It partially worked, here is the output:
1
3.21
2
3
5.22
4
5
4.67
Process returned 8 (0x8) execution time : 0.024 s
Press any key to continue.
It did only print when i had the correct values, but for some reason it only printed the first 3 lines, even though fgets was supposed to have been run 5 times by the last iteration, and so the pointer should have been reading the last line.
Can someone explain why the pointer did not update as expected and if there is an easier way to slice or index through a file in c.
You need to account for (at least) two additional characters, in addition to the numbers you have in the file. There is the end-of-line delimiter (\n on UNIX/Mac, or possibly \r\n on Windows... so maybe 3 additional characters), plus (from the fgets documentation):
A terminating null character is automatically appended after the characters copied to str.
A lot of the C functions that manipulate character arrays (ie. strings) will give you this extra null "for free" and it can be tricky if you forget about it.
Also, a better way to loop over the lines might be:
#define MAX_CHARS 7
char buf[MAX_CHARS];
while((fgets(buf, MAX_CHARS, fp)) != NULL) {
printf("%s\n", buf);
}
It's still not the best way to do it (no error checking) but a little more compact/readable and idiomatic C, IMO.

fscanf c programming wierd error

I am not new to programming, but I encountered this small problem and I can't seem to get it.
I want to read a file with dates and put them in another file with another format
Input example: 18.08.2015
Output example: 18-08-2015
Here is the code (dat1 has "r" permission and dat2 "w"):
char d[3];
char m[3];
char g[5];
while(fscanf(dat1,"%s.%s.%s\n",&d,&m,&g)==3)
{
fprintf(dat2,"%s-%s-%s\n",d,m,g);
}
On the other hand, this works fine if I use [space] instead of a [dot] in the input file.
(18 08 2015)
What am I missing? The solution has to be as simple as possible and with using fscanf, not fgetc or fgets, to be explained to students that are just beginning to learn C. Thanks.
The %s pattern matches a sequence of non-white-space characters, so the first %s will gobble up the entire string.
Why use char arrays at all, why not int?
int d;
int m;
int g;
while(fscanf(dat1,"%d.%d.%d\n",&d,&m,&g)==3)
{
fprintf(dat2,"%d-%d-%d\n",d,m,g);
}
The %d in fprintf will not output leading zeros though. You'll have to teach your students a little bit extra or leave it for extra credit.
Since the scanf format %s reads up to the next whitespace character, it cannot be used for a string ending with a .. Instead use a character class: %2[0-9] or %2[^.]. (Change the 2 to the maximum number of characters you can handle, and don't forget that the [ format code does not skip whitespace, so if you want to do that, put a space before the format code.)
Change
fscanf(dat1,"%s.%s.%s\n",&d,&m,&g)
to
fscanf(dat1,"%[^.].%[^.].%[^.]\n",d,m,g);

How do you scan redirected files in C (STDIN)?

Say I'm calling a program:
$ ./dataset < filename
where filename is any file with x amount of line pairs where the first line contains a string and second line contains 10 numbers separated by spaces. The last line ends with "END"
How can I then start putting the first lines of pairs (string) into:
char *experiments[20] // max of 20 pairs
and the second lines of the pairs (numbers) into:
int data[10][20] // max of 20, 10 integers each
Any guidance? I don't even understand how I'm supposed to scan the file into my arrays.
Update:
So say this is my file:
Test One
0 1 2 3 4 5 6 7 8 9
END
Then redirecting this file would mean if I want to put the first line into my *experiments, that I would need to scan it as such?
scanf("%s", *experiments[0]);
Doing so gives me an error: Segmentation fault (core dumped)
What is incorrect about this?
Say my file is simply numbers, for ex:
0 1 2 3 4 5 6 7 8 9
Then,
scanf("%d", data[0][0]); works, and will hold value of '1'. Is there an easier way to do this for the whole line of data? i.e. data[0-9][0].
find the pseudo-code, code explains how to read the input
int main()
{
char str[100]; // make sure that this size is enough to hold the single line
int no_line=1;
while(gets(str) != NULL && strcmp(str,"END"))
{
if(no_line % 2 == 0)
{
/*read integer values from the string "str" using sscanf, sscanf can be called in a loop with %d untill it fails */
}
else
{
/*strore string in your variable "experiments" , before copying allocate a memory for the each entry */
}
no_line++;
}
}
The redirected file is associated with the FILE * stdin. It's already opened for you...
otherwise, you can treat it the same as any other text file, and/or use the functions that are dedicated to standard input - with the only exception that you cannot seek in the file and not retrieve the size of the input.
For the data sizes you're talking about, by far the easiest thing to do is just slurp all of the content into a buffer and work on that: you don't have to be super-stingy, just make sure that you don't overrun.
If you want to be super-stingy with memory, preallocate a 4kB buffer with malloc(), progressively read() into it from stdin, and realloc() another 4kB every time the input exceeds what you've already read. If you don't care so much about being stingy with memory (e.g. on a modern machine with gigabytes of memory), just malloc() something much bigger than the expected input (e.g. a megabyte) and bug out if the input is more than that: this is far simpler to implement but less general/elegant.
You then have all of the input in a buffer and you can do what you like with it, which depends too strongly on the format of the input for me to say how you should approach that part.

Reading and comparing numbers from txt file C

I am new to C programming, so I am having difficulties with the problem below.
I have a text file inp.txt which contains information like the following:
400;499;FIRST;
500;599;SECOND;
670;679;THIRD;
I need to type a number and my program needs to compare it with numbers from the inp.txt file.
For example, if I type 450, it's between 400 and 499, so I need write to the word FIRST to the file out.txt
I have no idea how to convert a character array to an int.
I think you'll want these general steps in your program (but I'll leave it to you to figure out how you want to do it exactly)
Load each of the ranges and the text "FIRST", "SECOND", etc. from the file inp.txt, into an array, or several arrays, or similar. As I said in the comment above, fscanf might be handy. This page describes how to use it - the page is about C++, but using it in C should be the same http://www.cplusplus.com/reference/clibrary/cstdio/fscanf/. Roughly speaking, the idea is that you give fscanf a format specifier for what you want to extract from a line in a file, and it puts the bits it finds into the variables you specify)
Prompt the user to enter a number.
Look through the array(s) to work out which range the number fits into, and therefore which text to output
Edit: I'll put some more detail in, as asker requested. This is still a kind of skeleton to give you some ideas.
Use the fopen function, something like this (declare a pointer FILE* input_file):
input_file = fopen("c:\\test\\inp.txt", "r") /* "r" opens inp.txt for reading */
Then, it's good to check that the file was successfully opened, by checking if input_file == NULL.
Then use fscanf to read details from one line of the file. Loop through the lines of the file until you've read the whole thing. You give fscanf pointers to the variables you want it to put the information from each line of the file into. (It's a bit like a printf formatting specifier in reverse).
So, you could declare int range_start, range_end, and char range_name[20]. (To make things simple, let's assume that all the words are at most 20 characters long. This might not be a good plan in the long-run though).
while (!feof(input_file)) { /* check for end-of-file */
if(fscanf(input_file, "%d;%d;%s", &range_start, &range_end, range_name) != 3) {
break; /* Something weird happened on this line, so let's give up */
else {
printf("I got the following numbers: %d, %d, %s\n", range_start, range_end, range_name);
}
}
Hopefully that gives you a few ideas. I've tried running this code and it did seem to work. However, worth saying that fscanf has some drawbacks (see e.g. http://mrx.net/c/readfunctions.html), so another approach is to use fgets to get each line (the advantage of fgets is that you get to specify a maximum number of characters to read, so there's no danger of overrunning a string buffer length) and then sscanf to read from the string into your integer variables. I haven't tried this way though.

Resources