Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
this code gives an instant seg fault,I tried placing printf's all over, I even tried to printf something just after the int=0; line but no matter what I did, it does not print anything but a segmentation fault. The file exists, also its location is the same with where I do the execution.
The file includes city names, one name on each line, nothing else, how do I read them and store them in an array :/
what if there was a number after each city, would the reading still be the same?
NewYork 5
LosAngeles 12
California 7
and the code;
int i=0;
char **city_names = malloc(sizeof(char*));
FILE* fp;
fp = fopen("abc.txt","r");
while(!feof(fp)){
city_names[i] = realloc(city_names[i],sizeof(char)*255);
fscanf(fp,"%s",city_names[i]);
i++;
}
fclose(fp);
You are only allocating a single char * of memory in your malloc then accessing beyond it in the while loop.
If you are going to do a 2D malloc array, you need to malloc each pointer, then malloc assign a malloc into each to the max string size (yuck).
char **city_names = malloc(sizeof(char *) * kNumCities);
for(int i = 0; i < kNumCities; i++)
city_names[i] = malloc(sizeof(char) * kMaxStringSize);
Or do something like char city_name[3][256] instead to get it up and running.
I'd also like to add that this sort of reading is very unsafe. You are reading an unknown amount of bytes into a fixed buffer size. If the string you read in were more than 255 bytes, you will destroy memory. You'd be better off using an fread() into a fixed size buffer type solution (or ftell() then file and read it all in at once for best efficiency) and then do your reading off the buffer. Not to mention all the overhead of malloc and realloc (they do add up).
And the while(!feof(fp)) logic is wrong too; for an empty file it still tries to scanf something and increments i.
Never test for EOF before you read in C. Test after reading.
The idiomatic code to iterate over characters on stdin in C is
int c; /* NOT char. */
while ((c = getchar()) != EOF) {
/* do something with c */
}
To iterate over lines:
char line[MAXLINE];
while (fgets (line, sizeof line, stdin) != NULL) {
/* do something with line */
}
int i=0;
char **city_names = malloc(sizeof(char*));
FILE* fp;
fp = fopen("data.txt","r");
while(!feof(fp)){
city_names[i] = (char*)malloc(sizeof(char)*255);
if(1!=fscanf(fp,"%s %*d",city_names[i]))break;
++i;
city_names = (char**)realloc(city_names, (i+1)*sizeof(char*));
}
fclose(fp);
Related
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 4 years ago.
Improve this question
I want to create an array of character pointers (strings) of length 6
But I want to initialize them by iterating through a file which has \n separated exactly 6 lines
char* a[6];
FILE *fp = fopen("test.txt", "r");
for (int i = 0; i < 6; i++)
{
fgets(a[i], MAXLEN, fp);
}
But it gives me a segmentation error.
If someone can first write the code for this and then explain what is exactly wrong, it will be great, thanks.
Here
char* a[6];
a is an array of six char pointer and here
fgets(a[i], MAXLEN, fp); /* a[i] is a pointer & it doesn't have valid address, storing something into unreserved memory causes seg.fault */
it cause the segmentation fault because you are trying to store MAXLEN bytes into each a[i] but you didn't allocate memory for the same to store into it. Hence either first allocate memory for each a[i] like below & then store data into it or you can use two dimensional char array like char a[num_of_line][max_char_line];.
for (int i = 0; i < 6; i++) {
a[i] = malloc(MAXLEN); /* you can allocate as per req. */
fgets(a[i], MAXLEN, fp); /* read manual page of fgets(), it stores \n at end of buffer in some condition, be aware of that */
}
Also check the return value of fopen() and fgets(). And once usage of dynamic memory is done, free the dynamically allocated memory to avoid memory leakage.
This question already has answers here:
Getting a stack overflow exception when declaring a large array
(8 answers)
Closed 5 years ago.
I need to read in a line of text, store it into an array. When I compile the program, it works but then when I execute it, I receive a segmentation fault. I have read other questions and tried what they have suggested and nothing seems to be working.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main() {
FILE *file;
char text[10000000], *line[10000000];
int i=0;
file = fopen("/home/Documents/xxxxxx_HW01/text.txt", "r");
if(file == NULL) {
printf("cannot open file");
exit(1);
}
while (i< 10000 && fgets(text, sizeof(text), file)!= NULL){
line[i] = strdup(text);
i++;
}
for (i=0; text[i] != '\0'; i++)
printf("%c ", text[i]);
fclose(file);
}
Continuing from my comment,
text[i] = strdup (text);
Is wrong. It attempts to assign a pointer (the result of strdup) to text[i] a signed char value. You need to use a separate array of pointers (or declare a pointer to pointer to char, e.g. char **lines; and then allocate pointers and then for each line).
The most important thing you can do is Listen to what your compiler is telling you. To make sure you are getting the benefit of your compilers help, always compile with warnings enabled and do not accept code until it compiles without warning. For gcc that means adding at minimum -Wall -Wextra to your compile string. For clang, -Weverything will do. For cl.exe (VS) add /Wall. Then read and understand the warnings. The compiler will give you the exact line where any problem occurs.
If you are simply reading lines less than some number, you can avoid allocating pointer and just use an array of pointers, but you must keep track of the index (to avoid writing beyond the last element)
Based on what you are attempting, it looks like you are trying to do something similar to the following:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 1000
int main (void) {
FILE *file;
char text[MAX] = "",
*lines[MAX] = {NULL};
int i=0, j;
file = fopen ("/home/Documents/xxxxxx_HW01/text.txt", "r");
if(file == NULL) {
printf("cannot open file");
exit(1);
}
while (i < MAX && fgets (text, sizeof(text), file)!= NULL){
size_t len = strlen (text); /* get length */
if (len && text[len-1] == '\n') /* check if last is '\n' */
text[--len] = 0; /* overwrite with '\0' */
else { /* line too long - character remain unread */
fprintf (stderr, "error: line exceeds %d chars.\n", MAX - 2);
exit (EXIT_FAILURE);
}
lines[i] = strdup(text);
i++;
}
for (j = 0; j < i; j++) {
printf ("line[%3d] %s\n", j, lines[j]);
free (lines[j]); /* don't forget to free memory */
}
fclose(file);
return 0; /* main() is type int and therefore returns a value */
}
note: you should also remove the trailing '\n' included at the end of text by fgets -- example given above.
Look things over and let me know if you have further questions.
From what I remember sizeof will give you the size of the object type, and the fgets expects the maximum amount of chars you want to read, so you probably don’t want to use sizeof there.
Also you are increasing the index of your array indefinitely which is most likely going to give you a out of bounds exception.
Summing up I think you should try passing directly the size you set on your array on the fgets, and if you dont need the file to be all stored at the same time, just don’t increase i and handle each chunk in one iteration of the loop. If you do need the file all stored at once, make sure you have an array as big as your file size and perhaps use fread like this
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
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
I'm just a young computer science student, and currently I'm a bit confused about what is the best practice to read a string from stdin. I know that there are a lot of ways to do that, some safer than other, and so on...
I'm currently in need of a function that prevents buffer overflow and appends a null terminator character (\0) to the end of the string. I found fgets really useful for that, but ... It stops reading with \n or EOF! What if I want the user to input more than one line at time? Are there some other function that can help me doing that?
I'm sorry if this question can seem silly to some of you, but please, understand me!
Any help would be appreciated.
#define INITALLOC 16 /* #chars initally alloced */
#define STEP 8 /* #chars to realloc by */
#define END (-1) /* returned by getline to indicate EOF */
#define ALLOCFAIL 0 /* returned by getline to indicate allocation failure */
int getline(char **dynline)
{
int i, c;
size_t nalloced; /* #chars currently alloced */
if ((*dynline = malloc(INITALLOC)) == NULL)
return ALLOCFAIL;
nalloced = INITALLOC;
for (i = 0; (c = getchar()) != EOF; ++i) {
/* buffer is full, request more memory */
if (i == nalloced)
if ((*dynline = realloc(*dynline, nalloced += STEP)) == NULL)
return ALLOCFAIL;
/* store the newly read character */
(*dynline)[i] = c;
}
/* zero terminate the string */
(*dynline)[i] = '\0';
if (c == EOF)
return END;
return i+1; /* on success, return #chars read successfully
(i is an index, so add 1 to make it a count */
}
This function allocates memory dynamically, so the caller needs to free the memory.
This code is not perfect. If, on reallocation, there is a failure, NULL overwrites the previous, perfectly-good data causing a memory leak and loss of data.
If a newline is encountered and fgets returns, you can run it again as many times as necessary to read as many lines as you want. A loop is useful for this.
If EOF is encountered, you have reached the end of the file(/stream) and there is no point in running it again, because there is nothing left to read.
An example showing the logic to read an entire string to EOF from stdin follows.
There are many ways to do this, and this is just one, but it shows the general logic.
The result buffer grows as the input is read, and there are no bounds on this – so if EOF is never reached you will eventually run out of memory and the program will exit. A simple check could avoid this, or depending on your application you could process the data as it comes in and not need to store it all.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define LINE_BUFFER_SIZE 256
// Each time this is exhausted, the buffer will be increased in size by this amount again.
#define INITIAL_BUFFER_SIZE 2048
int main (int argc, char **argv) {
char *result = malloc(INITIAL_BUFFER_SIZE);
if (!result) {
// Out of memory.
return 1;
}
size_t totalBytesRead = 0;
size_t bytesAllocated = INITIAL_BUFFER_SIZE;
char buf[LINE_BUFFER_SIZE];
while (fgets(buf, LINE_BUFFER_SIZE, stdin)) {
size_t bytesRead = strlen(buf);
size_t bytesNeeded = totalBytesRead + bytesRead + 1;
if (bytesAllocated < bytesNeeded) {
char *newPtr = realloc(result, bytesAllocated + INITIAL_BUFFER_SIZE);
if (newPtr) {
result = newPtr;
bytesAllocated += INITIAL_BUFFER_SIZE;
}
else {
// Out of memory.
free(result);
return 1;
}
}
memcpy(result + totalBytesRead, buf, bytesRead);
totalBytesRead += bytesRead;
}
result[totalBytesRead] = '\0';
// result contains the entire contents from stdin until EOF.
printf("%s", result);
free(result);
return 0;
}
On POSIX systems, you have getline. It is able to read an arbitrarily wide line (till exhausting resources) in heap allocated memory.
You can also repeatedly call fgetc ... (BTW, you should define exactly what is a string for you)
On Linux, you can read an editable line from the terminal (that is, stdin when it is a tty) using GNU readline.
To read some kind of strings, you might use fscanf with e.g. %50s or %[A-Z] etc...
And you can read an array (of bytes, or some other binary data) using fread
You might read an entire line and parse it later (perhaps using sscanf). You could read several lines and build some strings in heap memory (e.g. using asprintf or strdup on systems having it) from them.
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;
}