I would like to store information from file in structure. My file consists of rows (each row has to be different structure) and columns, each column is different data. File looks like this:
1 AB
2 CD
3 CD
4 AB
My structure is this (where node number is first integer and node type is two letter):
struct nodes{
int nodeNumber;
char nodeType[2];
};
My code so far is this:
lines = lineCount(nodes); //calculates how many lines file has
struct nodes node[lines]; //creates structure array
no = fopen(nodes, mode);
if(no == NULL){
printf("Can't find the files.");
exit(1);
}else{
for(i = 0; i < lines; i++){
fscanf(no, "%d %2c \n", &id, current);
node[i].nodeNumber = id;
strcpy(node[i].nodeType, current);
}
}
when i debug current value is this: current = \"AB\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\" rather than just AB
any ideas?
The problem is your use of strcpy. It copies string, i.e. character arrays with a terminator. This means that strcpy will copy until it sees the string terminator character '\0' and put that at the end of the array, which means you will overwrite one byte outside of the array.
Either use manual copying character by character, a function such as memcpy, or increase the size of the array to three so it can fit the terminating character (which means you have to make sure the definition of current is also of size three, with a string terminator).
scanf does not nul-terminate characters read with the %c format code. (Although apparently current has lots of NULs, I don't know if you can count on that.
You should declare current as char[2], and use memcpy with a length of 2 instead of strcpy.
Related
I read somewhere that when we use structs we can't just write something like «example1.name = "Jim";», instead of it we should write «strcpy(example1.name, "Jim");»
The thing is that I need to use a struct and I need to scanf (and right after that sscanf) some information that corresponds to a string and I don't know how I should do it.
Could somebody help me, please?
Edit:
My code isn't complete and I know it's wrong, but I'll post it here so that you know what I am talking about:
int main(){
struct Cards{
int value;
char type[4];
};
for(i=1, 0 < i && i < 11, i++){
struct Cards cardi;
}
scanf("%d %s", &cardi.value, cardi.type);
/*at this point I just know it's wrong but I am really bugged.
I thought about something like «scanf("%d %s", &cardi.value, strcpy(cardi.type, "%s"));»
but I just know it's very wrong */
return 0;
}
This isn't true only about structs, but for all strings. You can use = for strings, only when you initialize them. You can scanf a string and place it in a string. Example:
scanf("%s", my_struct.str);
If you already have a string and you want to pass it in a struct, or in an other string variable you then need strcpy:
char str1[] = "abc", str2[4];
strcpy(str2, str1);
or
strcpy(my_struct.str, str1);
Edit:
for(i=1, 0 < i && i < 11, i++) {
struct Cards cardi;
}
In your code cardi is not card0, card1 etc, it is a struct Cards variable with the name cardi.
If you want to store 10 cards, you sould make an array of struct Cards with capacity of 10 like:
struct Cards array[10];
for (i = 0; i < 10; i++) {
scanf("%d %s", &array[i].value, array[i].type);
}
Anyway i suggest that you focus on learning the basics on arrays, strings and pointers before you use structs.
Edit 2: You don't want to define structs inside your main, because in that way, if you write a function it will not "see" your struct. Structs usually are written in the top of the code.
Your use of scanf() is correct. However scanning strings using %s is dangerous and discouraged. This is because the type member of your structure has space for only 4 characters, including the terminating '\0' (NUL) character. Entering a string longer than 3 characters will result in the extra characters being written into an unknown area of memory likely corrupting other variables and leading to incorrect program execution or a program crash. You can correct this by adding a string length limit, simply replace %s with %3s, where 3 is the maximum numbers of characters that will be accepted (scanf will automatically add a '\0' (NUL) character following the last scanned character).
Below are some additional comments:
If you want to declare an array for 10 Cards, you could do it this way without any loops:
struct Cards cardi[10];
To scan values into the first card (C arrays are 0-based):
// this will scan into the first card; type field is restricted to at most 3 characters
scanf("%d %3s", &cardi[0].value, cardi[0].type);
At the top of the file you'll want to add:
#include <stdio.h>
This header file provides a prototype (declaration) for the scanf function (among many others).
Example file:
School Name (with spaces)
FirstNameofStudent StudentID
School Name2 (with spaces)
FirstNameofStudent2 StudentID2
School Name3 (with spaces)
FirstNameofStudent3 StudentID3
I cant seem to figure out what to do after using fgets for the first line.
If by itself, I can easily get school name using fgets
and the second line by itself using fscanf then converting the studentID to int using atoi.
But how do I combine both fgets and fscanf?
The information scanned would be placed into an array.
Before I go onto the solution, I want to point out that an array can only have a single type. You cannot store integers in an array of characters.
Meaning if you would like all of this information to go in a single 2D array, you'd need to store the ID as a string. Then if you need it as an integer, you'd need to use atoi on it once you retrieve it.
Now for combining the two, you'd need a while loop with fgets in the condition in order to retrieve the first line. Something like this:
while(fgets(schoolname, 255, fp) != 0){ ... }
This would keep on retrieving lines until it fails, or it reaches EOF. However, you wanted to use fscanf for the second line, and for that, you'd need a line like this:
fscanf(fp, "%s %s\n", name, id);
This means, from the current point, there are two strings seperated by a space, and a newline. Store the two strings in name and id, and gobble the newline.
Gobbling the newline is key, as if you don't do it, the next time fgets runs, it would only find a single newline on the line.
As for storing the elements in an array, you'd need a 2D array of strings. For that, you can either do it fixed, or dynamic. For fixed, it's pretty easy, just have a line like char students[3][3][80] and simply store stuff in there, but for dynamic, you'd need to use memory allocation, pointers, etc, with a variable liks char ***students
Here's the code I used to solve your problem, though I suggest trying to do this on your own as well, to get the hang of it:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(){
FILE *fp = fopen("ex.txt", "r");
if(fp == 0) exit(-1);
char ***students;
// Used to check how many students there are
int studentno = 0;
// Init students array
// So far it means 1 ROW, with 3 COLUMNS, each of 80 CHARACTERS
students = calloc(studentno+1, 3 * 80);
// Temporary variables for storage
char schoolname[80];
char name[20];
char id[10];
int i = 0;
while(fgets(schoolname, 255, fp) != 0){
studentno++;
// Retrieve name and id from second line
fscanf(fp, "%s %s\n", name, id);
// Cut off newline left from fgets
schoolname[strlen(schoolname)-2] = 0;
// Allocate memory for new members of array
students[i] = malloc(3 * 80);
students[i][0] = malloc(80);
students[i][1] = malloc(80);
students[i][2] = malloc(80);
// Copy strings received into array
strcpy(students[i][0], schoolname);
strcpy(students[i][1], name);
strcpy(students[i][2], id);
// Resize students array for additional students
students = realloc(students, (size_t) (studentno+1) * 3*80);
i++;
}
// Check students are stored correctly
for(int i = 0; i < studentno-1; i++){
printf("%s - %s - %s\n", students[i][0], students[i][1], students[i][2]);
}
}
I need to append a array inside a linked list with a single character of an array also inside a linked list. I tried the strcat function but it didn't work.
for(int k=0; k < strlen(Node2->array); k++){
strcat((char *)Node->array, (char *)Node2->array[k]);
}
The ide gives this warning
cast to pointer from integer of different size -wint-to-pointer-cast
and I when I run the program the program stops, it can't go on.
There's no means to append to an array in C, as arrays are, per definition fixed (at compile time) lists of same type elements stored contiguously. Only if you have enough array size, a string (which is some char array which is partially filled by appending a \0 null character at the end of the valid char list) can be appended by simply moving the \0 char one place further (if there's place in the array for a character more) and putting before it the desired char. An example will illustrate this (I'll somewhat simplify to separate the list problem you point that has nothing to do with the appending problem)
Let's have:
char c = 'A';
char array[100] = "The string to be appended with ";
The second variable is an array initialized with the contents of the string literal indicated, plus \0 chars to complete array size until filling the 100 characters space of the array.
Several ways to append the contents of c variable are:
/* check first that array has space to store data */
int l = strlen(array);
if (l + 1 < sizeof array) {
array[l] = c;
array[l+1] = '\0';
}
Another way (if you don't need to know if the operation succeeded and only append the character if space is allocated) is to snprintf(3) the char at the end of the string value (the snprintf(3) controls correctly the space)
int l = strlen(array); /* number of chars in string */
snprintf(array + l, /* char pointer at string end */
sizeof array - l, /* the number of chars of space available */
"%c", /* format string to print a character */
c); /* data character to append */
By the way, the return value of snprintf(3) is the number of characters printed, so it should be 1 in case it worked successfully, and 0 in case there's no space left in the array to print the c variable and the final \0 character, so you can check the result of the operation.
NOTE
If you have a char * pointer in the node structure, because you allocated dynamically the memory to store the string value (for example, using strdup(3) function) then you have no space to append any character at the end as strdup(3) only allocates enough space to store a full copy (the characters, plus the extra \0 at the end) of the original string (even if that string was originally stored in a bigger character array) In this case, the only way to append a character is to allocate a new array with enough size for the new length and copy all the characters to the new place. Be careful, that if you do this in a per character basis, you'll get efficiency severely affected.
I want read text file and store in array then show.
This is my code:
int i = 0, line = 5;
char ch[100];
FILE *myfile;
myfile = fopen("test.txt","r");
if (myfile== NULL)
{
printf("can not open file \n");
return 1;
}
while(line--){
fscanf(myfile,"%s",&ch[i]);
i++;
printf("\n%s", &ch[i]);
}
fclose(myfile);
return 0;
}
This is my text:
test 123562
856
59986
But result:
est
2356
56
9986
What is wrong? :(
ch[i] is holding a single character. Statement fscanf(myfile,"%s",&ch[i]); will scan string to ch[i] which can hold only one character. There is no place for '\0' which leads your program to undefined behavior.
Change
fscanf(myfile,"%s",&ch[i]);
to
fscanf(myfile,"%s",ch);
Previous answer was wrong. Behavior of program is well defined but you are scanning the file in a wrong manner. Your program will work as expected if you place i++; after printf statement.
while(line--){
fscanf(myfile,"%s",&ch[i]);
printf("\n%s", &ch[i]);
i++;
}
The reason is that &ch[i] is a pointer to the ith element of the array and string will be stored in array starting at position i. For the input given, this will work because the given array is large enough to hold the string.
You can do this as:
while(line--){
fscanf(myfile,"%s",ch);
printf("\n%s", ch);
i++;
}
but it will overwrite the array ch each time a string is scanned to it. Better to use a two dimensional array to store strings and read file with fgets.
You're not going to be able to fit five lines in the single char ch[100] array; that's just an array of 100 characters.
You can make it an array of arrays, i.e. char ln[5][100] which will give you room for five lines of 100 characters each.
Then you of course need to index into that array in the loop, i.e.:
for(int i = 0; i < 5; ++i)
{
if(fgets(ln[i], sizeof ln[i], myfile) == NULL)
{
fprintf(stderr, "Read error on line %d\n", i);
exit(1);
}
}
This uses fgets() which is much better suited at reading in whole lines; fscanf() will stop at whitespace with %s which is seldom what you want.
There is no need to use the ampersand in the scanf while getting the string. Make that into like this.
fscanf(myfile,"%s",&ch[i]);
to
fscanf(myfile,"%s",ch);
&ch[i] It will get the character for i th position in that array. If you want to get like that you can use the %c instead of %s. And change this one to.
printf("\n%s", ch);
While printing the string when you use the ampersand(&) that will access the address of that variable.
The program developed must be able to read the input files containing matrix A and matrix B
using fopen function
a. Matrix A and B of different size may be stored in different input file (if required).
Scan and assign matrix A and B as array using fscanf function and for loop
Perform matrix operations
a. Add matrix A and B
b. Subtract matrix A and B
c. Multiply matrix A and B
Use conditional statement if or switch for switching between 3, 4 and 5 elements matrix.
Print all input matrices and results obtained in a new file called output.dat using fprintf
function.
The output.dat file must have a header with the following information:
a. Student name
b. Student matric number
c. Class section
d. Lecturer name
e. Project title
Below the header, the output file must contain matrix A and B and the results from matrix
operation.
Use matrix A and B as given below:
I'm reading in from a file that has a hex value on each line. It will look like this:
F0BA3240C
083FA52
45D3687AF
etc.
The hex values won't have the same length.
I have fgets reading from this file into a buffer and then a piece of code to get rid of the newline character. From there I put the string from the buffer into my data array. But before putting the string from the buffer into my data array, I'm attempting to compare the string from the buffer to the strings already stored in the data array and see if there is or isn't a match so I can update some counters. However, I'm having issues using strcmp and strncmp. Any help will be appreciated, thanks.
Relevant code:
char **data = NULL;
char data_buffer[100];
//program first goes through the file and determines amount of lines there are hence this variable
int count_line = 0;
...
data = malloc(count_line * sizeof(char *));
int f;
int i;
for(i=0; i<count_line; i++)
{
fgets(data_buffer, sizeof(data_buffer), fp);
...
//allocate space to store copy of line and add one for null terminator
data[i] = malloc(line_length + 1);
...
if(asdf != NULL)
{
//problem here. don't know how to compare stream from buffer and compare to all elements of data buffer
for(f=0; f<sizeof(data); f++)
{
if(strcmp(data[f], data_buffer) == 0)
there_was_a_match++;
}
}
...
//copy string from buffer into data array
strcpy(data[i], data_buffer);
}
Consider these lines:
for(f=0; f<sizeof(data); f++)
{
if(strcmp(data[f], data_buffer) == 0)
there_was_a_match++;
}
What is the value of sizeof(data)? Since data is of type char**, presumably
sizeof(data) is the size of a pointer in bytes, so some fixed integer value such as 4 or 8.
Now observe that the first time you encounter this loop within the "for i" loop,
i is 0 and data[0] is the only pointer in the array of pointers that has been allocated--
every other pointer in data is invalid.
So now what happens is, we do the first iteration of the inner loop: f is 0, so we
end up comparing the string we just read to itself.
On the next iteration, f is 1, we try comparing our latest string to data[1],
but data[1] has not yet been initialized,
ergo we have undefined behavior (such as a crash).
You might be better off if the f loop were like this:
for(f=0; f<i; ++f)
{
if(strcmp(data[f], data_buffer) == 0)
there_was_a_match++;
}
This way, you will compare the newest string (which you have just saved in data[i])
with only the strings that were already loaded.
There is one other thing that may be troublesome. Suppose your input consists of four
copies of the same string.
Then after you read the second copy and execute this loop, there_was_a_match will be 1;
after reading the third copy and executing that loop, there_was_a_match will be 3
(because it matches twice);
after reading the fourth copy and executing that loop, there_was_a_match will be 6.
I suspect these are not the results you want.
Perhaps you want to break out of the loop after finding the first match.
I can´t see problems with strcmp/strcpy, but:
for(f=0; f<sizeof(data); f++)
You can´t use sizeof, ie. it won´t result in the value count_line.
From the shown code, this could be enough to make it work.
Just compare to the previous allocated lines, which is i lines.
// for(f=0; f<sizeof(data); f++)
for(f=0; f<i; f++)