C reading from file: Reading only first char of line [closed] - c

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I have to get node ids from DIMES ASNodes.csv (http://netdimes.org/new/?q=node/65) files.
File looks like this:
6067,UNKNOWN,2007-02-03 10:03:53.0,2007-01-02 02:54:13.0,12,6,0
29287,UNKNOWN,2007-02-03 21:11:07.0,2007-01-02 07:33:35.0,1,0,0
...
So far I came up with this code, but it doesn't work quite right. Althought it prints out all the numbers I needed, it also prints out the node id twice and sometimes prints zeroes in between. Thanks for any ideas
void loadNodes(const char* filename)
{
FILE* nodes = fopen(filename, "r");
unsigned int id = 0;
char line[64];
while (fgets(line, sizeof(line), nodes) != NULL) {
sscanf(line, "%u%*[^\n]", &id);
printf("id = %u\n", id);
}
fclose(nodes);
}
output

I think the trouble is that your lines have 63 characters plus a newline, which means that the fgets() reads up to, but not including, the newline (and you process that and get the correct number), then the next fgets() reads the newline that was left behind on the previous input (and you process that — it is surprising that you get zeros rather than a repeat of the previous number).
Here's your code converted into an MCVE (How to create a Minimal, Complete, and Verifiable Example?) main() program that reads from standard input (which saves me from having to validate, open and close files):
#include <stdio.h>
int main(void)
{
unsigned id = 0;
char line[64];
while (fgets(line, sizeof(line), stdin) != NULL)
{
printf("Line: [%s]\n", line);
sscanf(line,"%u", &id);
printf("id = %u\n", id);
}
return 0;
}
Note the diagnostic printing of the line just read. The code should really check the return value from sscanf(). (There was no virtue in skipping the trailing debris, so I removed that from the format string.)
Given the data file (data):
6067,UNKNOWN,2007-02-03 10:03:53.0,2007-01-02 02:54:13.0,12,6,0
29287,UNKNOWN,2007-02-03 21:11:07.0,2007-01-02 07:33:35.0,1,0,0
The output I get from so.37103830 < data is:
Line: [6067,UNKNOWN,2007-02-03 10:03:53.0,2007-01-02 02:54:13.0,12,6,0]
id = 6067
Line: [
]
id = 6067
Line: [29287,UNKNOWN,2007-02-03 21:11:07.0,2007-01-02 07:33:35.0,1,0,0]
id = 29287
Line: [
]
id = 29287
Avoiding the problem
The simplest fix is to use a longer buffer length; I normally use 4096 when I don't care about what happens if a really long line is read, but you might decide that 128 or 256 is sufficient.
Otherwise, I use POSIX getline() which will read arbitrarily long lines (subject to not running out of memory).
With a longer line length, I get the output:
Line: [6067,UNKNOWN,2007-02-03 10:03:53.0,2007-01-02 02:54:13.0,12,6,0
]
id = 6067
Line: [29287,UNKNOWN,2007-02-03 21:11:07.0,2007-01-02 07:33:35.0,1,0,0
]
id = 29287

Assuming you only need the first column from the file (since you mention node ids), you could use:
unsigned int node_id;
char str[100];
while(scanf("%u,%[^\n]",&node_id, str) == 2) {
printf("%u\n",node_id);
}
Demo

Related

How can I read and process this kind of file [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 8 years ago.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Improve this question
I 12 0
I 9 1
I 26 0
I 25 2
B 26
P 0
R 25
A
So, what I need to do is read a file containing these characters/numbers and whenever I encounter a letter, I call a function to process whatever comes after the letter (aka the numbers).
For example:
When reading "I" I have to call the function to INSERT a certain number in a certain level of a Skip List; or when reading B, I need to search for a specific number in the Skip List, etc.
Problem is I'm really bad at reading from a file, can you guys enlighten me?
You can do this with file operations in c,
i am just giving you hints,
FILE *pFilePtr; // file pointer(handle of file)
pFilePtr = fopen(argv[1],"r");
//define buffer to store data read line by line data
char buf[32]={0};
//Now you can run a while loop to read entire file
with fread() to get whole first line(until '\n')
while(!feof(pFilePtr))
{
if(NULL != fgets(buf,32,pFilePtr))
// perform string operation on buffer to extract letters and digits
// and according to that call functions you need
}
#include <stdio.h>
#include <string.h>
int main(void) {
FILE *fptr;
char mystring[20];
int number;
fptr = fopen("Input.txt", "r");
while(fscanf(fptr , "%s %d", mystring, &number) != EOF) {
printf("%s %d\n", mystring, number);
if(strcmp(mystring, "I") == 0) {
printf("Implement the reqd function here\n");
}
}
}

Text file with different data types into structure array [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I have to parse a text file with 3 different data types. I want it to be saved in a structure array with three members. My text file look like this:
A B 45.78965
A C 35.46731
B C 46.78695
The program that I'm reading it with is the following and it does not work.
What am I doing wrong?
#include <stdio.h>
struct gra {
char from;
char to;
double w;
};
int main ()
{
FILE *fp = fopen("graph.txt", "r");
int i = 0;
while (!feof(fp)) {
fscanf(fp, "%[^\t]", &graph[i].from, &graph[i].to, &graph[i].w);
i++;
}
fclose(fp);
}
One of your problems is that you're reading using %[^\t], which reads strings, and store the result to variables that are not character arrays (two characters and a double).
Although it's not clear from your question, it seems that the lines of your input contain two characters and one real number separated by one tab character. If that is so, you should use the following fscanf to read them:
fscanf(fp, "%c\t%c\t%lf\n", &graph[i].from, &graph[i].to, &graph[i].w);
If you are not sure what exactly separates your fields and you want to allow any amount of white space in between and also extra white space in the beginning and end of the line, then use:
fscanf(fp, " %c %c%lf\n", &graph[i].from, &graph[i].to, &graph[i].w);
that is, use an extra space in the format before each "%c" to explicitly skip white space.
Your code has also a couple of other problems:
You are using feof to check for end of file. This will usually not work well if you're not reading the file character by character. Instead, you should check if your fscanf returned 3, that is, if it successfully read the three things that you wanted it to read.
You are missing a definition of array graph.
I'm adding the complete code that I'd write for doing the parsing:
#include"stdio.h"
#define MAX 100
struct {
char from, to;
double w;
} graph[MAX];
int main ()
{
FILE *fp = fopen("graph.txt", "rt");
for (int i=0; i<MAX; i++)
if (fscanf(fp, " %c %c%lf\n", &graph[i].from, &graph[i].to, &graph[i].w) < 3)
break;
fclose(fp);
return 0;
}

Text file with different data types into structure arrays [duplicate]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I have to parse a text file with 3 different data types. I want it to be saved in a structure array with three members. My text file look like this:
A B 45.78965
A C 35.46731
B C 46.78695
The program that I'm reading it with is the following and it does not work.
What am I doing wrong?
#include <stdio.h>
struct gra {
char from;
char to;
double w;
};
int main ()
{
FILE *fp = fopen("graph.txt", "r");
int i = 0;
while (!feof(fp)) {
fscanf(fp, "%[^\t]", &graph[i].from, &graph[i].to, &graph[i].w);
i++;
}
fclose(fp);
}
One of your problems is that you're reading using %[^\t], which reads strings, and store the result to variables that are not character arrays (two characters and a double).
Although it's not clear from your question, it seems that the lines of your input contain two characters and one real number separated by one tab character. If that is so, you should use the following fscanf to read them:
fscanf(fp, "%c\t%c\t%lf\n", &graph[i].from, &graph[i].to, &graph[i].w);
If you are not sure what exactly separates your fields and you want to allow any amount of white space in between and also extra white space in the beginning and end of the line, then use:
fscanf(fp, " %c %c%lf\n", &graph[i].from, &graph[i].to, &graph[i].w);
that is, use an extra space in the format before each "%c" to explicitly skip white space.
Your code has also a couple of other problems:
You are using feof to check for end of file. This will usually not work well if you're not reading the file character by character. Instead, you should check if your fscanf returned 3, that is, if it successfully read the three things that you wanted it to read.
You are missing a definition of array graph.
I'm adding the complete code that I'd write for doing the parsing:
#include"stdio.h"
#define MAX 100
struct {
char from, to;
double w;
} graph[MAX];
int main ()
{
FILE *fp = fopen("graph.txt", "rt");
for (int i=0; i<MAX; i++)
if (fscanf(fp, " %c %c%lf\n", &graph[i].from, &graph[i].to, &graph[i].w) < 3)
break;
fclose(fp);
return 0;
}

How would I compare a string (entered by the user) to the first word of a line in a file?

I am really struggling to understand how character arrays work in C. This seems like something that should be really simple, but I do not know what function to use, or how to use it.
I want the user to enter a string, and I want to iterate through a text file, comparing this string to the first word of each line in the file.
By "word" here, I mean substring that consists of characters that aren't blanks.
Help is greatly appreciated!
Edit:
To be more clear, I want to take a single input and search for it in a database of the form of a text file. I know that if it is in the database, it will be the first word of a line, since that is how to database is formatted. I suppose I COULD iterate through every single word of the database, but this seems less efficient.
After finding the input in the database, I need to access the two words that follow it (on the same line) to achieve the program's ultimate goal (which is computational in nature)
Here is some code that will do what you are asking. I think it will help you understand how string functions work a little better. Note - I did not make many assumptions about how well conditioned the input and text file are, so there is a fair bit of code for removing whitespace from the input, and for checking that the match is truly "the first word", and not "the first part of the first word". So this code will not match the input "hello" to the line "helloworld 123 234" but it will match to "hello world 123 234". Note also that it is currently case sensitive.
#include <stdio.h>
#include <string.h>
int main(void) {
char buf[100]; // declare space for the input string
FILE *fp; // pointer to the text file
char fileBuf[256]; // space to keep a line from the file
int ii, ll;
printf("give a word to check:\n");
fgets(buf, 100, stdin); // fgets prevents you reading in a string longer than buffer
printf("you entered: %s\n", buf); // check we read correctly
// see (for debug) if there are any odd characters:
printf("In hex, that is ");
ll = strlen(buf);
for(ii = 0; ii < ll; ii++) printf("%2X ", buf[ii]);
printf("\n");
// probably see a carriage return - depends on OS. Get rid of it!
// note I could have used the result that ii is strlen(but) but
// that makes the code harder to understand
for(ii = strlen(buf) - 1; ii >=0; ii--) {
if (isspace(buf[ii])) buf[ii]='\0';
}
// open the file:
if((fp=fopen("myFile.txt", "r"))==NULL) {
printf("cannot open file!\n");
return 0;
}
while( fgets(fileBuf, 256, fp) ) { // read in one line at a time until eof
printf("line read: %s", fileBuf); // show we read it correctly
// find whitespace: we need to keep only the first word.
ii = 0;
while(!isspace(fileBuf[ii]) && ii < 255) ii++;
// now compare input string with first word from input file:
if (strlen(buf)==ii && strstr(fileBuf, buf) == fileBuf) {
printf("found a matching line: %s\n", fileBuf);
break;
}
}
// when you get here, fileBuf will contain the line you are interested in
// the second and third word of the line are what you are really after.
}
Your recent update states that the file is really a database, in which you are looking for a word. This is very important.
If you have enough memory to hold the whole database, you should do just that (read the whole database and arrange it for efficient searching), so you should probably not ask about searching in a file.
Good database designs involve data structures like trie and hash table. But for a start, you could use the most basic improvement of the database - holding the words in alphabetical order (use the somewhat tricky qsort function to achieve that).
struct Database
{
size_t count;
struct Entry // not sure about C syntax here; I usually code in C++; sorry
{
char *word;
char *explanation;
} *entries;
};
char *find_explanation_of_word(struct Database* db, char *word)
{
for (size_t i = 0; i < db->count; i++)
{
int result = strcmp(db->entries[i].word, word);
if (result == 0)
return db->entries[i].explanation;
else if (result > 0)
break; // if the database is sorted, this means word is not found
}
return NULL; // not found
}
If your database is too big to hold in memory, you should use a trie that holds just the beginnings of the words in the database; for each beginning of a word, have a file offset at which to start scanning the file.
char* find_explanation_in_file(FILE *f, long offset, char *word)
{
fseek(f, offset, SEEK_SET);
char line[100]; // 100 should be greater than max line in file
while (line, sizeof(line), f)
{
char *word_in_file = strtok(line, " ");
char *explanation = strtok(NULL, "");
int result = strcmp(word_in_file, word);
if (result == 0)
return explanation;
else if (result > 0)
break;
}
return NULL; // not found
}
I think what you need is fseek().
1) Pre-process the database file as follows. Find out the positions of all the '\n' (carriage returns), and store them in array, say a, so that you know that ith line starts at a[i]th character from the beginning of the file.
2) fseek() is a library function in stdio.h, and works as given here. So, when you need to process an input string, just start from the start of the file, and check the first word, only at the stored positions in the array a. To do that:
fseek(inFile , a[i] , SEEK_SET);
and then
fscanf(inFile, "%s %s %s", yourFirstWordHere, secondWord, thirdWord);
for checking the ith line.
Or, more efficiently, you could use:
fseek ( inFile , a[i]-a[i-1] , SEEK_CURR )
Explanation: What fseek() does is, it sets the read/write position indicator associated with the file at the desired position. So, if you know at which point you need to read or write, you can just go there and read directly or write directly. This way, you won't need to read whole lines just to get first three words.

the first fwrite works but not the second [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
I don't know why the first fwrite() for customer, works, but not the second fwrite() for the symbol of the message. My program wants to check if the customer and the symbol from the message already contained in the library.dat. Here is my piece of code :
typedef struct {
char Name[50];
int totalmsg;
int totalword;
} Customer;
typedef struct {
char symbol;
char alphabet[20];
} Ssymbol;
void add_customer () {
boolean found;
int i;
fp = fopen("customer.dat", "wb+");
fread(&Customer_history, sizeof(TabInt), 102, fp);
i = GetLastIdx(Customer_history);
do {
printf ("Please input customer's name: ");scanf("%s",&temp);
if (i == 0) {
i++;
SetName(&Customer_history,i,temp);
SetMsg(&Customer_history,i,i);
SetEff(&Customer_history,i);
printf("Do you still wanna add another customer ?(Y/N)"); scanf("%s",&CC);
}
else {
found = Search_name(Customer_history,temp);
if (found == true) {
printf("The name is already exist \n\n");
}
else {
i++;
SetName(&Customer_history,i,temp);
SetMsg(&Customer_history,i,i);
SetEff(&Customer_history,i);
}
printf("Do you still wanna add another customer ?(Y/N)"); scanf("%s",&CC);
}
} while ((CC == 'y') || (CC =='Y'));
fwrite(&Customer_history, sizeof(Customer), 102, fp);
fclose(fp);
}
void add_symbol() {
char tempc;
char tempalphabet[20];
boolean found;
int i;
fp = fopen("library.dat","wb+");
fread(&list_symbol, sizeof(Ssymbol), 52, fp);
i = GetLastIdx2(list_symbol);
do{
printf("Please input new symbol:");
scanf("%s", &tempc);
printf("Please input the alphabet of the symbol:");
scanf("%s", &tempalfabet);
if (i==0){
i++;
SetSymbol(&list_symbol,i,tempc);
SetAlphabet(&list_symbol,i,tempalphabet);
printf("Do you want to add another symbol? (Y/N)");
scanf("%s",&CC);
}
else{
found = Search_symbol(list_symbol, tempc);
if (found==true){
printf("Symbol is already exist \n\n");
}
else{
i++;
SetSymbol(&list_symbol,i,tempc);
SetAlphabet(&list_symbol,i,tempalphabet);
printf("Do you want to add another symbol? (Y/N)");
scanf("%s",&CC);
}
}
}
while((CC=='y') || (CC=='Y'));
fwrite(&list_symbol, sizeof(Ssymbol),52, fp);
fclose(fp);
}
If you are only expecting a single character here:
scanf("%s", &tempc);
then change it to:
scanf("%c", &tempc);
otherwise, you need to define tempc as an array (and don't use &).
Here also, since tou are passing an array, you should not use address-of (&):
printf("Please input the alphabet of the symbol:");
// scanf("%s", &tempalfabet); is wrong
scanf("%s", tempalfabet); // correct
Inspect all scanf calls in your code and fix them
It's hard to say without a more "compile-able" version of your code... Here're some points for you:
A) boolean is not a type in C. You'll need something like:
#include <stdbool.h> // or some other header that defines bool
typedef bool boolean;
Failing that:
typedef int boolean;
#define false 0
#define true 1
B) add_customer() and add_symbol() using fp which is not defined. You need to define a FILE * fp for those operations.
C) The following (I assume to be) methods are not defined: GetLastIdx(), SetName(), SetMsg(), SetEff(), Search_Name(), GetLastIdx2(), SetSymbol(), SetAlphabet(), Search_symbol()
D) The following (I assume to be) global variables and data structers are not defined: Customer_history, TabInt, temp, CC, list_symbol, tempalfabet
Based on your problem description I assume you have this working, so these should all be defined. If you can provide a more complete, compile-able version of your code showing the problem, I could be of more help.
So based on what I have, here's some input:
1) You are reading into your list_symbol, this should be a pointer to a block of memory big enough for 52*sizeof(Ssymbol), this should be around 1092 bytes.
fread(&list_symbol, sizeof(Ssymbol), 52, fp);
Also note that if list_symbol is an array of Ssymbols then your read code be screwed up by the fact that you have an array in your structure, fread() will read and fill your data exactly byte for byte. For example:
Ssymbol list_symbol[52];
FILE * fp = fopen("test.txt", "r");
memset(list_symbol, 0, 52*sizeof(Ssymbol));
fread(list_symbol, sizeof(Ssymbol), 52, fp);
And let's says "test.txt" has in it:
C abcdefghijklmn
3 12345678
Then your list_symbol will look like:
list_symbol[0].symbol = 'C'
list_symbol[0].alphabet = ' abcdefghijklmn3 12' //note the newline and spaces fill it
list_symbol[1].symbol = '3'
list_symbol[1].alphabet = '45678'
And that might not be what you wanted to do. Make sure your data matches your structures!
2) Your one scanf() that you completely show is wrong:
char tempc;
...
scanf("%s", &tempc);
You want "%c" if you want a character, not "%s". I don't see the other declarations (see point D) above, however based on your prints and your usage I can tell you tempalfabet and CC are almost certainty wrong as well.
3) Your scanf()s are going to leave newline characters unless you consume them:
printf("Please input new symbol:");
scanf("%c\\n", &tempc); // <-- escaped newline will do that for you
4) You open your files with "wb+". See fopen() options that's for writing and appending to a binary file. If you want a binary file to read and write you need: "ab+", if you want a text file "a+" will do.
5) You do not reset the file pointer:
fopen(file for reading, writing, and appending);
fread(stuff);
do c code;
fwrite(stuff);
This will result in what you have written being appended to the bottom of your file. I don't know if that's what you wanted. So this might not be a problem if you wanted to read a full list_symbol worth of data, then append a new set to the bottom of your file. I suspect that you wanted to overwrite what was in your file however... in which case you need to fseek() back to the beginning, or you can simply close and open the file.
I am trying to guess the issue, since the entire code is not vailable..
Is it possible that the number of symbols is exceeding 52, and you are writing only first 52 symbols? So fwrite is indeed working, but it is not changing the data file. Try printf'ing i(=GetLastIdx2), to see if it is exceeding 52.
Also, instead of having array for list_symbols, I would recommend using a linked list & fread/fwrite, using a while loop, to read/write all the symbols in the data file.
From the code logic, it want to read some data from file and then update it.
Then you should use "rb+" mode to open the file, instead of "wb+" which truncate the whole data. With "wb+" mode, the file data is truncated and the fread() should return 0, the whole do/while becomes invalid.
I don't know why the first fwrite() works, both of them should not.
In all, try ab+ mode in fopen(), and don't forget to call fseek() with SEEK_SET to reset the file position indicator before calling fwrite(), it may resolve your problem.

Resources