Reputation: 109
I've been working on a program where I need to use C to scan lines from a file and store them in a struct.
My .txt file is in the form:
NAME 0.2 0.3
NAME2 0.8 0.1
Or in general its a string followed by 2 doubles
My struct is:
struct device {
char* name;
double interruptProbability, interruptTime, startTime, endTime;
} myDevice;
Now, I'm able to scan the lines in fine, but when it comes time to put them into my struct, something gets messed up. Here's how I'm doing the scanning:
char line[BUFSIZ];
while(fgets (line, BUFSIZ, devicesFile) != NULL){
struct device *d = &myDevice;
if(!isspace(*line)){
printf("String: %s \n", &line);
d->name = "success"; // for testing purposes
printf("device name before: %s \n", d[0]);
sscanf(line, "%s %f %f",&d->name, &d->interruptProbability, &d->interruptTime);
printf("device name after: %s \n", d[0]);
}
}
When I run this, it'll print off:
String: Disk 0.2 0.00005
device name before: success
before giving me a seg fault.
I ran GDB to test whats going on with the scan, and for whatever reason it puts in d->name a huge hex number that has (Address out of bounds) next to it.
any ideas?
Upvotes: 0
Views: 173
Reputation: 6743
You're sscanf-ing into a string literal. String literals are const char*s in C and C++, are are readonly, so sscanf will crash whilst trying to write to the string literal "success".
Upvotes: 0
Reputation: 63481
You can't scan a string into the pointer d->name
.
Not even after you assign it a constant value:
d->name = "success"; // for testing purposes
You need to allocate memory for it, or make it an array. You should be very careful using sscanf
to read strings. It might be better to use strtok
or just strchr
to find the first space and then copy the bytes out with strdup
.
char *next = strchr(line, ' ');
if( next != NULL ) {
*next++ = 0; // Terminate string and move to next token.
d->name = strdup(line); // Make a copy of tokenised string
// Read the floats - note you should check that the result is equal to 2.
count = sscanf(next, "%f %f", d->interruptProbability, d->interruptTime);
}
Upvotes: 0
Reputation: 2743
You are not allocating space for each of your char *name
. You need to add d->name = (char *)malloc(<length of the token>*sizeof(char)+1)
before your sscanf call.
Upvotes: 0
Reputation: 409442
It's because you're overwriting a literal string in the sscanf
call. d->name
points to a literal string, and those are read-only and of a fixed length (so if the string you try to get is longer than 7 character you also try to write beyond the end).
You need to either use an array for d->name
or allocate memory on the heap for it.
Upvotes: 1