I'm having a lot of difficulty doing this! What I do is get the first line to initialize an array of pointers, then want to point those blocks to variables that contain the string from the text document. However; even when I read all the values into the array they are all pointing to the same variable which changes as the file is being read. Is there way I can copy those values into the array without them all pointing to the changing line as the file is being read?
int main(void){
FILE * fp;
char line[256];
int i = 0;
int digit = 0;
fp = fopen("testfile","r");
if(fp == NULL){
printf("Cannot Open File");
}
fgets(line,sizeof(line),fp);
digit = atoi(line);
printf("digit = %d\n",digit);
char *rest[digit];
while(!feof(fp)){
while (i < digit){
fgets(line,sizeof(line),fp);
fgets(line,sizeof(line),fp);
printf("line = %s",line);
char arr[sizeof(line)+1];
strcpy(arr,line);
rest[i] = arr;
printf("restaurant = %s",rest[i]);
i++;
}
the text file is as follows:
6
Outback Steakhouse
Red Robin
Max & Erma’s
Chipotle
Panera
BW3
8
Stephanie 5 3 2 4
Chris 4 6 5 1
Peter 5 2 4 1
Josh 1 4 3 6
Jessica 5 2 3 4
Al 6 4 2 3
Adam 5 1 3 2
Eric 1 4 3 5
You need to copy the values into dynamically allocated memory. strdup will do. Replace:
char arr[sizeof(line)+1];
strcpy(arr,line);
rest[i] = arr;
With:
rest[i] = strdup (line);
Also you call fgets twice.
Additionally, when line is too long, it will be not zero terminated. To make it safe always assign zero at the end of line.
Related
I have a 2D array representing a sudoku grid defined like this:
int** sudoku = (int**)malloc(sizeof(int*) * 9);
for(i = 0; i < 9; i++)
sudoku[i] = (int*)malloc(sizeof(int) * 9);
I've run it through a function that iterates through every element and prints, which works fine (displays 81 zeros). But then, I hand it to another function that reads a grid from a file into this array. Here's what it looks like (with a bunch of printf statements I'm using for debugging omitted).
void readSudokuFile(char* filename, int*** grid) {
FILE* file;
int i, j, curr;
file = fopen(filename, "r");
for(i = 0; i < 9; i++) {
for(j = 0; j < 9; j++) {
fscanf(file, "%d", &curr);
*grid[i][j] = curr;
}
}
fclose(file);
}
When the function is running, it appears to read find for the first row, but when it gets to the second row and tries to insert a value into sudoku[1][0], I get a seg fault. This is what the output looks like with my printfs in:
Reading line 0...
Reading col 0... got 6
Reading col 1... got 2
Reading col 2... got 4
Reading col 3... got 5
Reading col 4... got 3
Reading col 5... got 9
Reading col 6... got 1
Reading col 7... got 8
Reading col 8... got 7
Reading line 1...
Reading col 0... got 5
Segmentation fault(core dumped)
This is the file I'm trying to read in:
6 2 4 5 3 9 1 8 7
5 1 9 7 2 8 6 3 4
8 3 7 6 1 4 2 9 5
1 4 3 8 6 5 7 2 9
9 5 8 2 4 7 3 6 1
7 6 2 3 9 1 4 5 8
3 7 1 9 5 6 8 4 2
4 9 6 1 8 2 5 7 3
2 8 5 4 7 3 9 1 6
I'm compiling using gcc with -Wall and -pedantic, and am getting no compiler warnings.
I've googled around for a few hours to no avail, I'm not exactly sure what's going wrong here. Any help would be greatly appreciated.
To avoid pointer bugs you just ran into I suggest to simplify your dynamic 2D-array allocation like this ->
int (*array) [Y] = malloc(sizeof(int[X][Y]));
Access your array like this ->
int g=array[0][0];
And set like this ->
array[0][0]=0;
That will simplify your solution a lot and you also get a continuous memory block containing your 2D-array as a bonus. That will also simplify writing and reading files as you do not need to traverse each element if you do not necessarily have to do that for other reasons.
/A
Try modify your function like this:
void readSudokuFile(char* filename, int** grid) {
// ...
grid[i][j] = curr;
}
and invoke it like this:
readSudokuFile(filename, sudoku)
Hi i have this text file, where the first column in a character the 2nd and the third one is an integer.. but I'm not able to read and print the values correctley.
So this the file am trying to read:
c 6
o 4 3
o 2 4
o 3 2
o 1 1
o 3 3
And here is the code :
#include <stdio.h>
#include <stdlib.h>
#define N 6
int main (int argc, char *argv[])
{
int i;
int M[N];
int U[N];
char c ;
FILE* fichier = NULL;
fichier = fopen("pb1.txt","r");
if(fichier!= NULL )
{
while(!feof(fichier))
{
fscanf(fichier, "%c %d %d", &c, &M[i], &U[i]);
printf("%c %d %d \n", c, M[i],U[i]);
}
}
}
This is what the output looks like
c 6 1472131424
o 4 3
4 3
o 2 4
2 4
o 3 2
3 2
o 1 1
1 1
o 3 3
3 3
I have no clue why it gives me this. thank you
The first problem I see here, is you use the value of i uninitialized. It invokes undefined behavior.
To elaborate, i is an automatic local variable and unless intialized explicitly, will have an indeterminate value. Attempt to use that will lead to UB.
Also, you have never increased the value of i which is supposed to be used as the index for storing and printing the values.
Lastly, always check the return value of scanf() and family to ensure the success, before you try to use the scanned value.
That said, Please see Why is “while ( !feof (file) )” always wrong?
so I am trying to make a matrix reader that will take a text file that contains only data for a NxN matrix such as:
10 9 8 7
6 5 4 3
2 1 0 1
Read the test file into a dynamic multidimensional array. The program will not have headers, so it will need to read the entire file in order to obtain # of rows/cols.
Once I have all the data in my array I then will be able to manipulate how I want (i.e. swapping columns/rows, reversing order, etc).
At this point I am just trying to get my program to simply output the array as it appears in the test file once the entire matrix has been read in.
Here is what I have written so far:
#include <stdio.h>
#include <stdlib.h>
int main() {
int n;
int i=0;
int j=0;
scanf("%d", &n);
int **array;
array = malloc(n * sizeof(int *));
if(array == NULL) {
printf("Out of memory\n");
exit(1);
}
for(i = 0; i < n; i++) {
array[i] = malloc(n * sizeof(int));
if(array[i] == NULL) {
printf("Out of memory\n");
exit(1);
}
}
for(i = 0; i < n; i++) {
for(j = 0; j < n; j++) {
int k;
scanf("%d", &k);
array[i][j] = k;
printf("%d ", array[i][j]);
}
}
}
And running this gives me output:
9 8 7 6 5 4 3 2 1 0 1 1 1 1 1 1 1 1 1 1 1 1... repeating 1's...
I am not sure what is wrong with my code I have been staring at it for a solid hour and have made 0 progress.
Because my output prints out about 100 different ints I feel that my problem lies in my printing loops, and I feel like it has something to do with int n, but I am not sure how to deal with this.
Any help with be greatly appreciated! Thanks.
The issue is as follows: The first number that is obtained from your file is 10 and that is being stored inside the int n close towards the beginning. That value defines the width and height of your multi-dimensional array, your matrix. You then ask for further values from that file, exactly 10 * 10 many times.
The file, however, only has 4 * 3 - 1 = 11 numbers left in it. It provides them all, right into the int k. Those values get stored inside your matrix, printed. After the 11th (or 12th if you count the first 10) the scanf starts failing. As it fails, it returns the value EOF == -1 but you do not recognize that.
Failure leaves the k as it is, although I am not sure whether it is guaranteed to remain what it previously was, since as far as I know, k could very well have another memory location allocated for itself with each cycle, since (again) as far as I know it gets cleared at the end of each loop. In your case, it does keep its value, luckily I would say, and that gets stored/printed.
In the end, you should have exactly 100 numbers printed, because of that 10 at the very beginning.
Even if you had an additional 4 at the very beginning, you'd end up with a matrix that has a wild last line with all 1s.
If you want to have a 3 by 4 matrix in your hands, consider making your file as the following example:
3 4
10 9 8 7
6 5 4 3
2 1 0 1
Then read the first value into an int n and then second one into an int m. Make first memory allocation with malloc( n * sizeof * array );, then the secondary allocations with malloc( m * sizeof ** array );.
You could also alternatively omit reading anything, deduce how many rows and columns your matrix should have by reading the amount of new-line '\n' occurrences in your file (plus one), as well as amount of numbers there are on a single line.
Edit:
Okay, let's show this you could also part: This is just an example, I'll be using a pair of scanfs for counting both the amount of lines that have at least one number inside and amount of numbers on a single line.
...
int n = 0;
int m = 0;
int discardable;
while ( scanf( "%d", &discardable ) == 1 ) {
// as long as a number has been successfully read
n++;
if ( scanf( "%*[^\n]" ) != 0 )
// discard everything until a '\n'
// and if you fail to encounter a '\n' anywhere until the file ends...
break;
}
// rewind back to the beginning of the file
rewind ( stdin );
while ( scanf( "%d", &discardable ) == 1 ) {
// as long as a number has been successfully read
m++;
if ( scanf( "%*[ \t]" ) != 0 || stdin->_ptr[0] == '\n' )
// discard every ' ' or '\t'
// if you rather get carried until the end of file, break
// else, if the upcoming character is '\n', again, break
break;
}
rewind ( stdin );
...
There you have it, n and m here should be storing the height and width of the matrix you should have, respectively.
This is just a way to do it, I can see why many could potentially just hate this, because I have made use of the FILE structure, and referred to _ptr, but whatever. I personally would prefer this any day over carrying a temporary character array and read from it.
This question already has answers here:
How to read the standard input into string variable until EOF in C?
(5 answers)
Closed 9 years ago.
I have this graph (with the first line is number of vertices, the following lines are directed edges):
9
1 4
1 5
2 5
4 5
4 6
6 9
7 6
7 8
8 9
There is no information to know how many edges are in the input so can anyone suggest a way to read this kind of input?
Thank you you all,
I finally solved it, here is the input code:
while (1) {
tmp1 = scanf("%d", &x);
if (tmp1 == -1) // fix here
break;
tmp2 = scanf("%d", &y);
new_vertex = (Vertex *) malloc(sizeof(Vertex));
new_vertex->adj_vertex = NULL;
new_vertex->vertex_no = y;
new_vertex->time_stamp_visit = 0;
new_vertex->time_stamp_finish = 0;
last_vertex = getLastVertex((graph+x));
last_vertex->adj_vertex = new_vertex;
}
Loop over this list from 1 to n-1 read the pair and insert the edge between these two nodes in your graph data structure.
I advise reading this: http://shygypsy.com/iotutorial.html
And using the method under "Read integers, one at a time, skipping whitespace, until the end of input."
In your code maintain state on whether it's a beginning or a ending vertice being inputted.
Don't forget to press ctrl+d when done typing input.
You can use a "termination character" that counts as EOF, like a -1 or something after the last pair of nodes.
Then your data would be:
9
1 4
1 5
2 5
4 5
4 6
6 9
7 6
7 8
8 9
-1
And your code:
while(1){
scanf("%d %d", &num1, &num2);
if(num1==-1) break;
// process
}
I wrote getnum() to return an integer from stdin:
int getnum(int * last) {
int c, n = 0;
while ((c = getchar()) != EOF && 0x30 <= c && c < 0x40)
n = n * 10 + (c - 0x30);
if (last)
*last = c;
return n;
}
It will get digits from stdin until a non-digit character is retrieved. Because getnum() doesn't care what the non-digit character is, it doesn't matter how the numbers are arranged. They could all be on the same line, or in space-delimited pairs, one per line. I put this in a loop that stops once it reads in the right number of numbers, but you could easily loop until last pointed to non-whitespace.
Additionally, if you want to read from a FILE or fd (integer file descriptor), pass the FILE/fd to getnum() and use getc(FILE *)/fgetc(int).
gcc 4.4.4 c89
Is there a better way to do this?
I have the following code to read in from a text file. The text file contains lines like this:
4 5 6 1 5 7 5 9 5 3 5 7 8 3 2 3
7 2 3 4 5 3 7 9 3 2 5 6
I have given only 2 lines example, but there could be more and each with different lengths.
What I need to do is get the numbers into a buffer so that I can analsys them. Which is easy enough.
However, I am looking for a solution that won't overwrite the buffer for each line. So my result buffer should contain the following:
4 5 6 1 5 7 5 9 5 3 5 7 8 3 2 3 7 2 3 4 5 3 7 9 3 2 5 6
So I am using fgets to read in the lines, and passing that line to my analyse function.
However, I need the increment value in the for loop to start where the last one finished.
I have set the device_buff to static. Is that safe. I am not keen to use static variable inside a function, as they are not thread safe and constitutes to a global variable.
int g_load_devices_numbers(void)
{
fget(line_read, DEVICE_SIZE, fp) == NULL) {
analyse_device_numbers(line_read);
}
}
static void analyse_device_numbers(const char * const device_line)
{
size_t i = 0;
static char device_buff[1024] = {0};
static size_t device_counter = 0;
/* Start inserting the last index */
static size_t buff_counter = 0;
/* copy each number into the char array
* only copy up to the 'return' as fgets always inserts one */
for(i = 0; device_line[i] != '\n'; i++, buff_counter++) {
device_buff[buff_counter] = device_line[i];
/* Only count numbers and not spaces */
if(isspace(device_buff[buff_counter]) == 0) {
device_counter++;
}
}
/* nul terminate the vote buffer */
device_buff[buff_counter] = '\0';
}
Many thanks for any suggestions,
No, using a static buffer for device_buff is not safe here. Not because of the buffer itself, but because it has a limited size (1024 items) that is not checked.
It would be safer to provide as input parameters to analyse_device_numbers the buffer where data must be stored and the length of that buffer. Length must still be checked, to avoid writing after the last cell of the provided buffer and you have to choose some error management convention (like returning -1 from analyse_device_numbers when a buffer overflow occured).
To always write in the same target buffer the usual trick if to move the beginning of the provided buffer (to take into account items already stored) and to reduce the total length by the same amout. This can be done in the external loop that call g_load_device_numbers.