Question about reading int and String from array - c

I have two-dimensional arrays which contain the input from a file. I want to assign integers and strings from the array to different variables; the integer is set correctly, but the string is not working.
the input is like:
(1,2) apple 2 3 north
but all these information are inside:
char data[MAX_LINES][MAX_LEN];
I am trying to use sscanf to assign values:
sscanf(data[i],"(%d,%d) %8s %d %d %8s",&x,&y,type,&age,&hun,direction);
Code structure by ignoring unrelated code
FILE *in_file = fopen(fileName,"r");
char data[MAX_LINES][MAX_LEN];
int x,y,age,hun;
char type[10];
char deriction[20];
if(! in_file){
printf("cannot read file\n");
exit(1);
}
int line=0;
while(!feof(in_file) && !ferror(in_file)){
if(fgets(data[line],MAX_LEN,in_file) !=NULL ){
char *check = strtok(data[line],d);
line++;
}
}
fclose(in_file);
for(int i = 9; i<14;i++){
sscanf(data[i],"(%d,%d) %8s %d %d %8s",&x,&y,type,&age,&hun,deriction);
}

#include <stdio.h>
int main(){
//Data:
char data[1][100] = {"(1,2) apple 2 3 north"};
//Define variables:
int x, y, age, hun;
char type[10], direction[10];
sscanf(data[0], "(%d,%d) %s %d %d %s", &x, &y, type, &age, &hun, direction);
//Check by printing it out:
printf("(%d,%d) %s %d %d %s\n", x, y, type, age, hun, direction);
printf("x: %d\ny: %d\ntype: %s\nage: %d\nhun: %d\ndirection: %s", x, y, type, age, hun, direction);
//Success:
return 0;
}
If this doesn't work, then the problem might be the data in your array, data.

You have the line char *check = strtok(data[line],d);. You've not shown what d is, but unless it is a string with no characters in common with the input line, strtok() just mangled your stored data, zapping whatever is the first character from d with a null byte. That means your sscanf() will fail because it isn't looking at the whole line. If, perchance, you have const char d[] = "\r\n"; or equivalent, this ceases to be relevant, beyond pointing out that you should show enough code to reproduce the problem.

Related

I have problems with getting numbers from the file. Function fscanf reads only strings. 8

Fscanf does not work and I can't understand why. It only reads strings and nothing else.
1 2 3 is written in the file.txt.
Here's the code:
include<stdio.h>
int main()
{
FILE* ptr = fopen("file.txt","r");
if (ptr==NULL)
{
printf("no such file.");
return 0;
}
char* buf[100];
int a;
fscanf(ptr," %d ",a);
printf("%d\n", a);
fscanf(ptr," %s ",buf);
printf("%s\n", buf);
return 0;
}
There are several issues in your provided code, I would like to first talk about before getting to the answer you have asked for.
1.
fscanf(ptr," %d ",a);
This is false. Here the address of an int is needed as third argument. You need the ampersand operator & to access an address of a variable, like:
fscanf(ptr," %d ",&a);
2.
fscanf(ptr," %s ",buf);
Is also false. A pointer to a char array is needed here as third argument, but buf is declared as an array of 100 pointers after
char* buf[100];
You need to declare buf in the right way as a char array, like:
char buf[100];
to make it work with:
fscanf(ptr," %s ",buf);
3.
You have forgot the # in the include directive for stdio.h:
include<stdio.h>
Also, there should be a white space gap between #include and the file you want to include.
So the preprocessor directive should be look like:
#include <stdio.h>
4.
If the open stream operation fails you should not use return with a value of 0.
If an operation fails, that is crucial to the program itself, the return value of the program should be a non-zero value (the value of 1 is the most common) or EXIT_FAILURE(which is a macro designed for that purpose (defined in header <stdlib.h>)), not 0, which indicating to outer software applications as well as the operation system, that a problem has occurred and the program could not been executed successfully as it was ment for its original purpose.
So use:
if (ptr==NULL)
{
printf("no such file.");
return 1;
}
5.
Fscanf does not work and I can't understand why. It only reads strings and nothing else.
What did you expect as result? What do you want that fscanf()should do?
The format specifier %s is used to read strings until the first occurrence of a white space character in the input stream (skips leading white space characters until the matching sequence is encountered), pointed to by ptr.
Then I get from your header title:
I have problems with getting numbers from the file
that you want only the numbers from the file.
If you want to get the numbers only from the text file, you do not need the char array buf and the whole things with reading strings at all.
Simply use something like:
int a,b,c; // buffer integers.
fscanf(ptr,"%d %d %d",&a,&b,&c);
printf("%d %d %d\n",a,b,c);
Of course, this expressions implying that it only work with the given example of the 1 2 3 data or anything equivalent to (integer) (integer) (integer) but I think you get the idea of how it works.
And, of course, you can apply the scan operation by using fscanf() (and also the print operation by using printf()) for each integer separate in a loop, instead to scan/print all integers with just one call to fscanf() and printf(), f.e. like:
#define Integers_in_File 3
int array[Integers_in_File];
for(int i = 0; i < Integers_in_File; i++)
{
fscanf(ptr,"%d",&array[i]); // writing to respective int buffers,
} // provided as elements of an int array.
for(int i = 0; i < Integers_in_File; i++)
{
printf("%d",array[i]); // Output the scanned integers from
} // the file.
The whole program would be than either:
#include <stdio.h>
int main()
{
FILE* ptr = fopen("file.txt","r");
if (ptr==NULL)
{
printf("no such file.");
return 1;
}
int a,b,c; // buffer integers.
fscanf(ptr,"%d %d %d",&a,&b,&c);
printf("%d %d %d\n",a,b,c);
return 0;
}
Or that:
#include <stdio.h>
#define Integers_in_File 3
int main()
{
int array[Integers_in_File];
FILE* ptr = fopen("file.txt","r");
if (ptr==NULL)
{
printf("no such file.");
return 1;
}
for(int i = 0; i < Integers_in_File; i++)
{
fscanf(ptr," %d",&array[i]); // writing to respective intbuffers,
} // provided as elements of an int
// array.
for(int i = 0; i < Integers_in_File; i++)
{
printf("%d",array[i]); // Output the scanned integers from
} // the file.
return 0;
}
The variadic arguments to fscanf() must be pointers.
Whitespace is the default delimiter and need not be included in the format string.
If the input stream does not match the format specifier, the content remains buffered, and the argument is not assigned. You should therefore check the conversion which can fail due to mismatching content or EOF.
To declare an array for a character string, the array type must be char not char* - that would be an array of pointers, not an array of characters.
char buf[100];
int a;
if( fscanf( ptr, "%d", &a ) > 0 )
{
printf( "%d\n", a ) ;
if( fscanf(ptr, "%s", buf) > 0 )
{
printf( "%s\n", buf ) ;
}
}
Or simply:
char buf[100];
int a;
if( fscanf( ptr, "%d%s", &a, buff ) == 2 )
{
printf( "%d\n", a ) ;
printf( "%s\n", buf ) ;
}

fgets give me random big number

This is my code, I don't know how to use fgets after scanf so I am using fgets in the 26th line too but every time I use it, it give me big number(ex.2752100) but I write 2.
Why is it doing it?
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv)
{
char veta[100];
int line = 1;//tell what line it is on
int found = 0;
char a[100];//put the characters of the line into here
char b[100];
char linesearch[10];//the line you are looking for
FILE *file;//the file pointer
file = fopen("text.txt","r");//point the file
if (file == NULL)
{
printf("file does not exist or doesn't work\n");
return 0;
}
printf("Ahoj, naucim te psat snadno a rychle! \n");
printf("Vyber si uroven slozitosti od 1 do 10:\n");
//scanf("%d", &linesearch);
fgets(linesearch,10,stdin);
printf("\nHledam uroven %d ...\n\n",linesearch);
EDIT:
i have another problem:
while(fgets(a,100,file))
{
if(x == line)
{
found = 1;
printf("level %d found,level %d say: %s",x,x,a);
}
else
printf("reading level: %d\n",line );
line++;
}
printf("\nwrite your string as fast as you can!!");
fgets(veta,40,stdin);
if (strcmp(veta,a) == 0)
{
printf("\nwell done!!!!\n");
}
else
{
printf("\nwrong!!!!\n");
printf("%s", a);
printf("%s", veta);
}
i have small senteces(ex I like my mum and she likes me,etc) i want to compare my text with text from file and get answer if I write it well or not. Bonus points if it tell me how many mistakes i did it will be powerful!.
The fgets() function reads character data from the input. To convert this character data to an integer, use atoi() or a similar function.
fgets(linesearch, 10, stdin);
int x = atoi(linesearch);
printf("\nHledam uroven %d ...\n\n",x);
Your printf statement is printing out the address of the linesearch array, which will seem like a random big number.
If you want to read from stdin, into a char array, using scanf() and then print as an int:
scanf("%s", linesearch); // e.g. reads 1234 into array linesearch[].
printf(" %s ...\n\n",linesearch); // Prints string in array linesearch[].
printf(" %p ...\n\n",linesearch); // Prints base address of linesearch[].
int iNum = atoi(linesearch); // Converts string "1234" to number 1234.
printf(" %d ...\n\n",iNum); // Prints the converted int.
iNum++; // Can perform arithmetic on this converted int.
You are getting a big number from printf because you used %d in the format. The number is the memory address of your character array. To print the character array, update the format to %s.

C Array struct, trying to access data, but is coming up with the same for all arrays

So, my goal is to create a linear search, but i have got that down pat, I am having one problem with accessing strings from the struct, that i have stored using a txt file, so in linearSearch() I tried doing this:
printf("Name: %s \n", q.name[i]);
printf("Data: %d \n", q.data[i]);
The data would be perfect but name would just print out the same name for every array which would be the last item that I put into the array.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
char* name[10];
int data[10];
}Word;
//int bubblesort (Word word);
void linearSearch(char* name, Word q);
int main (int argc, const char *argv[]){
Word q;
char username[9]; /* One extra for nul char. */
int score;
int i = 0;
FILE *ifp, *ofp;
ifp = fopen("Data.txt", "r");
while (fscanf(ifp, "%s %d", &username, &score) == 2) {
q.name[i] = username;
printf ("Name: %s, I = %d \n", q.name[i], i);
q.data[i] = score;
printf ("Data: %d, I = %d \n", q.data[i], i);
i++;
}
linearSearch("Matt", q);
return EXIT_SUCCESS;
}
void linearSearch(char* name, Word q){
int i = 0;
int foundIt = 0;
int numNames = sizeof(&q.name);
while ((foundIt == 0) && (i <= numNames)){
printf("Name: %s \n", q.name[i]);
printf("Data: %d \n", q.data[i]);
if ((strcmp(name, q.name[i]) != 0)){
i = i + 1;
} else {
foundIt = 1;
}
}
if (foundIt == 1){
printf("Name found at position %d", i);
} else {
printf("Required person not found");
}
}
This happens because of the code
q.name[i] = username;
You cannot assign the value of an array using = operator. Here, you're assigning the address of username to every q.name[i]. So, the last value of username is reflected throughout the array.
What you actually need is to use malloc() to allocate memory and then strcpy() to copy the string contents.
Otherwise, you can also make use of strdup().
Either way, don't forget to free() the allocated ememory once you're done using them.
I can see that you declared char username[9], so I assume your names should be at most 8 characters long. You should :
read with : fscanf(ifp, "%8s %d",&username, &score) == 2 : the & is useless in front of an array (it decays nicely to a pointer), but you should limit size of input - ok , your problem does not come from there
use a 2D char array for Word.name instead of an array of pointers. That way your memory is already allocated and you can safely strcpy to it :
typedef struct {
char name[10][9];
int data[10];
}Word;
then :
strcpy(q.name[i], username); /* safe because qname[i] and username are both [9] */
The rule here is always control that you do not risk a buffer overrun when writing in char arrays/
An alternative way would be to do dynamic allocation through strdup but in that case you should free it.

fscanf() filter

I have a file with data in this format:
Name WeekDay Month day, Year StartHour:StartMin Distance Hour:Min:Sec
Example:
John Mon September 5, 2011 09:18 5830 0:26:37
I want to scan this into a struct:
typedef struct {
char name[20];
char week_day[3];
char month[10];
int day;
int year;
int startHour;
int startMin;
int distance;
int hour;
int min;
int sec;
} List;
i use fscanf():
List listarray[100];
for(int i = 0; ch = fgetc(file) != 'EOF'; ch = fgetc(file), i++){
if(ch != '\0'){
fscanf(file, "%s %s %s %d %d %d %d %d %d %d %d", &listarray[i].name...etc)
}
}
My issue is that I want to filter out the noise in the input string, that being:
Month day*,* year <- the comma is consistent in all entries. I just want the month in the char array, the day in int.
And the time stamps:
startHour:startmin and hour:min:sec <- here I want to filter out the colon.
Do I need to put it into a string first and then do some splitting, or can I handle it in fscanf?
Update:
Okay, så I've been trying to get this to work now, but I simply cannot. I literally have no idea what the issue is.
#include <stdio.h>
/*
Struct to hold data for each runners entry
*/
typedef struct {
char name[21];
char week_day[4];
char month[11];
int date,
year,
start_hour,
start_min,
distance,
end_hour,
end_min,
end_sec;
} runnerData;
int main (int argc, const char * argv[])
{
FILE *dataFile = fopen("/Users/dennisnielsen/Documents/Development/C/Afleveringer/Eksamen/Eksamen/runs.txt", "r");
char ch;
int i, lines = 0;
//Load file
if(!dataFile)
printf("\nError: Could not open file!");
//Load data into struct.
ch = getc(dataFile);
//Find the total ammount of lines
//To find size of struct array
while(ch != EOF){
if(ch == '\n')
lines++;
ch = getc(dataFile);
}
//Allocate memory
runnerData *list = malloc(sizeof(runnerData) * lines);
//Load data into struct
for(i = 0; i < lines; i++){
fscanf(dataFile, "%s %s %s %d, %d %d:%d %d %d:%d:%d %[\n]",
list[i].name,
list[i].week_day,
list[i].month,
list[i].date,
list[i].year,
list[i].start_hour,
list[i].start_min,
list[i].distance,
list[i].end_hour,
list[i].end_min,
list[i].end_sec);
printf("\n#%d:%s", i, list[i].name);
}
fclose(dataFile);
return 0;
}
I've been told that "only strings to do not require & in front of them in fscanf();" but I tried both with and without ampersand to no avail.
Put the "noise" in the format string.
Also you might like to limit the size of strings.
And get rid of the & for arrays.
And test the return value from scanf!
// John Mon September 5, 2011 09:18 5830 0:26:37
if (scanf("%19s%2s%9s%d,%d%d:%d%d%d:%d:%d", ...) != 11) /* error */;
// ^^^ error: not enough space
Notice week_day has space for 2 characters and the zero terminator only.
You can put this noise in the scanf format string.
Note also that for date/time strings, you can use strptime. It does the same kind of job that scanf, but is specialized on date/times. You will bo able to use %Y, %M ... and other with it.

Reading in from a file in C

I need to read from a file from using C.
#include <stdio.h>
struct record{
char name[2];
int arrival_time;
int job_length;
int job_priority;
};
const int MAX = 40;
main(){
struct record jobs[MAX];
FILE *f;
fopen("data.dat","rb");
int count =0;
while(fscanf(f, "%c%c %d %d %d", &jobs[count].name, &jobs[count].arrival_time, &jobs[count].job_length, &jobs[count].job_priority) != EOF){
count++;
}
int i;
for(i =0;i<count;i++){
printf("%c%c %d %d %d", &jobs[count].name, &jobs[count].arrival_time, &jobs[count].job_length, &jobs[count].job_priority);
}
}
The data file's format is the following:
A1 3 3 3
B1 4 4 4
C1 5 5 5
...
First one is char[2] and the other three int. I can't get the code right to read in until the end of file.
Anyone come across this before?
Updated Code.
There are a couple of modifications needed - most notably, you need to reference the jobs array of structures:
#include <stdio.h>
struct record{
char name[2];
int arrival_time;
int job_length;
int job_priority;
};
const int MAX = 40;
int main(void)
{
struct record jobs[MAX];
int i = 0;
int j;
FILE *f = fopen("data.dat","rb");
while (fscanf(f, "%c %d %d %d", &jobs[i].name[0], &jobs[i].arrival_time,
&jobs[i].job_length, &jobs[i].job_priority) == 4 && i < MAX)
i++:
for (j = 0; j < i; j++)
printf("%c %d %d %d\n", jobs[j].name[0], jobs[j].arrival_time,
jobs[j].job_length, jobs[j].job_priority);
return(0);
}
I make sure the loop doesn't overflow the array. I print the data out (it is the most basic form of checking that you've read what you expected). The most subtle issue is the use of jobs[i].name[0]; this is necessary to read and print a single character. There's no guarantee that there is any particular value in jobs[i].name[1]; in particular, it is quite probably not an NUL '\0', and so the name is not null terminated. It seems a bit odd using a single character name; you might want to have a longer string in the structure:
char name[MAX]; // Lazy reuse of MAX for two different purposes!
fscanf(f, "%.39s ...", jobs[i].name, ...
printf("%s ...", jobs[i].name, ...
The & is now not needed. The %.39s notation is is used to read a length-limited string up to the first space. Note that the size in the string is one less than the size of the array. It can often be simplest simply to create the format string with sprintf() to get the size right.
The code does not error check the fopen() statement.
Your code prints out A 1 3 3 instead of A1 3 3 3. I tried to add a second %c to it and it did not resolve it.
I discussed names longer than one character...
If you need to read "A1", you need the name member to be bigger so that you can null terminate the string, and you need to use %s rather than %c to read the value, and you need to lose the & and subscript, and you need to protect your code from buffer overflow (because where you expect 'A1', someone will inevitably enter 'A1B2C3D4D5F6G7H8I9J10K11L12M13' and wreak havoc on your code if you do not protect against the buffer overflow. Incidentally, the change in the test of the result of fscanf() (from == EOF to != 4 was also a protection against malformed input; you can get zero successful conversions without reading any characters, in general - though your %c would eat one character per iteration).
#include <stdio.h>
struct record{
char name[4];
int arrival_time;
int job_length;
int job_priority;
};
const int MAX = 40;
int main(void)
{
struct record jobs[MAX];
int i = 0;
int j;
FILE *f = fopen("data.dat","rb");
while (fscanf(f, "%.3s %d %d %d", jobs[i].name, &jobs[i].arrival_time,
&jobs[i].job_length, &jobs[i].job_priority) == 4 && i < MAX)
i++:
for (j = 0; j < i; j++)
printf("%s %d %d %d\n", jobs[j].name, jobs[j].arrival_time,
jobs[j].job_length, jobs[j].job_priority);
return(0);
}
You need to get the line and parse it according to the type you want to read.
while(fgets(line, 80, fr) != NULL)
{
/* get a line, up to 80 chars from fr. done if NULL */
sscanf (line, "%s %d %d %d", &myText, &int1, &int2, &int3);
}
See example here:
http://www.phanderson.com/files/file_read.html
Note: this is not the best way, someone else has answered with a much easier solution using format strings and fgets which will basically do what i wanted to do in one easy line.
I am assuming you want something like this. Note that I have not tested this at all as I just wrote it out pretty quickly.
#include <stdio.h>
FILE *fileInput;
main()
{
char* path="whatever.txt";
fileInput = fopen(path, "r");
int i=0;
while (fgets(line,100,fi)!=NULL)
{
token[0] = strtok(line, " ");
//now you can do whatever you wanna do with token[0]
//in your example, token[0] is A1 on the first iteration, then B1, then C1
while(token[i]!= NULL)
{
//now token[i] can be converted into an int, probably using atoi
//in your example, token[i] will reference 3 (3 times) then 4, etc
}
}
}
Hope it helps!
No, the lines do not contain ints. Each line is a string which can be easily parsed into four shorter strings. Then each of the strings can either be extracted and stored in your struct, or converted to ints which you can store in your struct.
The scanf function is the usual way that people do this kind of input string parsing when the data format is simple and straightforward.

Resources