including <stdlib.h> causes segmentation fault - c

I am writing a program to read info from a text file and I had everything working. The problem is that I am trying to add the functionality to calculate the mean of some of fields and have to convert the strings to doubles. I noticed that atof would work in some cases but would return -1 for the most part. i then realized that I didn't include stdlib, so I added that, but now I am getting a segmentation fault with just that one change.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
main(int argc, char *argv[]){
int numParts=10;
long numTests=49000;
char filename[] = "sweep_data.txt";
FILE *fp= fopen(filename,"r");
FILE *out= fopen("TesterData.csv", "w+");
FILE *meanf= fopen("meanData.txt", "w+");
char delims[] = " <>";
char *result = NULL;
char line [128];
char *TestNum=NULL;
char *TestName=NULL;
char *TestName2=NULL;
char *SequencerName=NULL;
char *lowlim=NULL;
char *hilim=NULL;
char *value=NULL;
char *units=NULL;
char *DeviceNum=NULL;
char ValueArray[numTests][10];
char ***ValuePtr = NULL;
char InfoArray[numTests][20];
char ***InfoPtr = NULL;
double mean[numTests];
long sum;
int intResult;
int count=0;
int DeviceCount=-1;
int i,j, m,n,k,a,b, len, mLen;
/*Allocate Memory for 2D arrays*/
ValuePtr = malloc(numParts * sizeof *ValuePtr);
for(i=0; i<numParts;i++){
ValuePtr[i]=malloc(numTests*sizeof *ValuePtr);
for(j=0; j<numTests; j++){
ValuePtr[i][j] = malloc(strlen(ValueArray[j]) +1);
}
}
InfoPtr = malloc(6 * sizeof *InfoPtr);
if(InfoPtr != NULL){
for(a=0; a<6;a++){
InfoPtr[a]=malloc(numTests*sizeof *InfoPtr);
for(b=0; b<numTests; b++){
InfoPtr[a][b]= malloc(strlen(InfoArray[b]) +1);
}
}
}
while(fgets(line, sizeof line, fp) != NULL){
result = strtok(line, delims);
TestNum=result;
intResult = strtol(result, NULL, 10);
if(intResult ==0){
if(strcmp(result, "Device:")==0){
DeviceCount++;
count=0;
}
continue; //if doesn't start with a number go to next line
}
result = strtok(NULL, delims);
TestName= result;
result = strtok(NULL, delims);
TestName2= result;
result = strtok(NULL, delims);
SequencerName = result;
lowlim=SequencerName;
if(atof(SequencerName)>1 || atof(SequencerName)<-1){
result= strtok(NULL, delims);
lowlim=result;
strcat(TestName, TestName2);
}
else
SequencerName= TestName2;
if(strstr(TestName, "%")!=NULL || strcmp(TestName,"PTgen")==0 || strcmp(TestName,"mode")==0){
units="NA";
}
else if(strstr(TestName, "2nd") == NULL && strstr(TestName, "3rd") == NULL){
result= strtok(NULL, delims);
units = result;
}
result= strtok(NULL, delims);
value=result;
if(strstr(TestName, "%")==NULL && strcmp(TestName,"PTgen")!=0 && strcmp(TestName,"mode")!=0){
result=strtok(NULL, delims);
if(strstr(TestName, "2nd") != NULL || strstr(TestName, "3rd") != NULL)
units = result;
}
result=strtok(NULL, delims);
hilim=result;
if(hilim[strlen(hilim)-1]=='\n'){
hilim[strlen(hilim)-1]='\0';
hilim[strlen(hilim)-1]='\0';
}
if(DeviceCount==0){
strcpy(InfoPtr[0][count], TestNum);
strcpy(InfoPtr[1][count], TestName);
strcpy(InfoPtr[2][count], SequencerName);
strcpy(InfoPtr[3][count], lowlim);
strcpy(InfoPtr[4][count], hilim);
strcpy(InfoPtr[5][count], units);
}
strcpy(ValuePtr[DeviceCount][count],value);
count++;
}
for(b=0;b<numTests;b++){
sum=0;
for(a=0;a<numParts;a++){
fprintf(meanf, "%s\n", ValuePtr[a][b]);
sum=atof(ValuePtr[a][b]);
fprintf(meanf, "%f\n",sum);
}
mean[b]=sum/numParts;
for(n=0; n<2;n++){
fprintf(meanf, "%s ", InfoPtr[n][b]);
}
fprintf(meanf, "%f\n",mean[b]);
}
printf("NumTests: %i\n",count); //number of tests run
printf("NumParts: %i\n", DeviceCount+1);//number of parts run
fprintf(out,"Test#, TestName,SeqName,LowLim,UpLim,Units,");
for(j=1; j<=numParts;j++){
fprintf(out," Device#%i,", j);
}
fprintf(out, "\n");
for (n = 0; n < numTests; n++) {
for(a=0;a<6;a++){
fprintf(out, "%s", InfoPtr[a][n]);
fprintf(out, ", ");
}
for (m =0; m < numParts ; m++) {
fprintf(out, "%s, ", ValuePtr[m][n]);
}
fprintf(out, "\n");
}
}
The part where I was needing to convert to a double is
for(b=0;b<numTests;b++){
sum=0;
for(a=0;a<numParts;a++){
fprintf(meanf, "%s\n", ValuePtr[a][b]);
sum+=atof(ValuePtr[a][b]);
fprintf(meanf, "%f\n",sum);
}
mean[b]=sum/numTests;
for(n=0; n<2;n++){
fprintf(meanf, "%s ", InfoPtr[n][b]);
}
fprintf(meanf, "%f\n",mean[b]);
}

The following line doesn't seem correct. It is using strlen on something that has not been initialized. So the results would be nondeterministic:
ValuePtr[i][j] = malloc(strlen(ValueArray[j]) +1);
The use of that later in the calls to atof() would quite possibly not produce consistent results. And depending on the actual allocation size, it could result in a seg fault when storing data in it.

Not that this has anything to do with the segfault, but:
ValuePtr = malloc(numParts * sizeof **ValuePtr);
...
InfoPtr = malloc(6 * sizeof **InfoPtr);

Related

How i can create a function for reading structure from a test.txt

How i can create a function for reading structure from a test.txt. I have a good works code in main, but i need to carry out it from main(). How combine (struct student PI1[N] and (fread() or fgets() or fwrite()));
struct student {
char surname[50];
char name[50];
char dayBirth[50];
int mark;
};
struct student PI1[N];
int main()
{
int counter = 0;
char str[50];
const char s[2] = " ";
char* token;
FILE* ptr;
int i = 0;
ptr = fopen("test.txt", "r");
if (NULL == ptr) {
printf("file can't be opened \n");
}
char* tmp;
int Itmp;
while (fgets(str, 50, ptr) != NULL) {
token = strtok(str, s);
strcpy(PI1[i].surname, token);
token = strtok(NULL, s);
strcpy(PI1[i].name, token);
token = strtok(NULL, s);
strcpy(PI1[i].dayBirth, token);
token = strtok(NULL, s);
Itmp = atoi(token);
PI1[i].mark = Itmp;
i++;
counter++;
}
}
Rather than "can create a function for reading structure from a test.txt", start with a function to convert a string from fgets() into a struct. Then call it as needed.
Use sprintf() and " %n" to detect complete scan with no extra text.
// Return success flag
bool string_to_student(struct student *stu, const char *s) {
int n = 0;
sscanf(s, "%49s%49s%49s%d %n", stu->surname, stu->name,
stu->dayBirth, &stu->mark, &n);
return n > 0 && s[n] == '\0';
}
Use
while (i < N && fgets(str, sizeof str, ptr) &&
string_to_student(&PI1[i], str)) {
i++;
}
counter = i;

How to read from the file and write it in the structure? I have a little trouble with my code

I have to write this code, I mean I should read from the file name of students and their mark, and then sort students by the grow of mark. Now I just want to output only mark. I want to display grades using structures. I don't know where the problem is.
text.file
Jon 3
Alina 5
Ron 1
#include <stdio.h>
#define _CRT_SECURE_NO_WARNINGS
#include <string.h>
#include <stdlib.h>
int main()
{
const int N = 3;
int i = 0;
struct student {
char surname[50];
int mark;
};
struct student PI1[N];
char str[50];
const char s[1] = " ";
char* token;
FILE* ptr;
token = strtok(str, s);
ptr = fopen("test.txt", "r");
if (NULL == ptr) {
printf("file can't be opened \n");
}
while (fgets(str, 50, ptr) != NULL){
token = strtok(str, s);
strcpy(PI1[i].surname, token);
token = strtok(NULL, s);
PI1[i].mark = atoi(token);
i++;
}
fclose(ptr);
printf("The marks is:\n");
printf("%d %d %d", PI1[0].mark, PI1[1].mark, PI1[2].mark);
return 0;
}
You need to prevent the program from reading from the file pointer if opening the file fails:
ptr = fopen("test.txt", "r");
if (NULL == ptr) {
perror("test.txt");
return 1; // this could be one way
}
The second argument to strok should be a null terminated string. const char s[1] = " "; only has room for one character. No null terminator (\0). Make it:
const char s[] = " "; // or const char s[2] = " "; or const char *s = " ";
Don't iterate out of bounds. You need to check so that you don't try to put data in PI1[N] etc.
while (i < N && fgets(str, sizeof str, ptr) != NULL) {
// ^^^^^^^^
Check that strok actually returns a pointer to a new token. If it doesn't, the line you've read doesn't fulfill the requirements.
while (i < N && fgets(str, sizeof str, ptr) != NULL) {
token = strtok(str, s);
if(!token) break; // token check
strcpy(PI1[i].surname, token);
token = strtok(NULL, s);
if (token) // token check
PI1[i].mark = atoi(token);
else
break;
i++;
}
You could also skip the strcpy by reading directly into your struct student since char str[50]; has the same length as surname. str should probably be larger though, but for now:
while (i < N && fgets(PI1[i].surname, sizeof PI1[i].surname, ptr) != NULL) {
token = strtok(PI1[i].surname, s);
if(!token) break;
token = strtok(NULL, s);
if (token)
PI1[i].mark = atoi(token);
else
break;
i++;
}
Only print as many marks as you successfully read
printf("The marks are:\n");
for(int idx = 0; idx < i; ++idx) {
printf("%d ", PI1[idx].mark);
}
putchar('\n');

Error when reading strings from CSV (Core Dumped)

I keep getting the same error, I'm new to programming so I'm not so sure if the Syntax is correct.
Every time I run it, it returns Segmentation Fault(core dumped), I'm not even sure If I can open a file with a string (address) instead of the filename in extense.
Also the files I'm reading from are CSV but in txt format.
I'm using C99
#define BUFFER_SIZE 1024
#define TAM_PERGUNTAS 128
struct question{
char category[TAM_PERGUNTAS];
char question[TAM_PERGUNTAS];
char option1[TAM_PERGUNTAS];
char option2[TAM_PERGUNTAS];
char option3[TAM_PERGUNTAS];
char correct[TAM_PERGUNTAS];
};
struct question vec_question[BUFFER_SIZE];
void questions() {
FILE *perguntas;
int numaleat=0;
int num_questions, counter = 0, index, temp_randomizer=0;
char line[BUFFER_SIZE];
char answer[32];
char address[TAM_PERGUNTAS];
address[0] = '\0';
srand(time(NULL));
printf("Digite agora o numero de perguntas desejadas.(MAX 20) : "); //Insert Number of questions
scanf("%d", &num_questions);
printf("\n");
for (counter = 0; counter < num_questions; counter++) {
temp_randomizer = rand() % j; //j Represents the number o CATEGORIES at play and acts as a marker in the SELECTION string
sprintf(address, "%s.txt", SELECTION[temp_randomizer]);
perguntas = fopen(address, "r");
if (perguntas == NULL) {
printf("ERROR OPENING FILE!");
}
index = 0;
while (fgets(line, sizeof(line), perguntas) != NULL) {
strcpy(vec_question[index].category, strtok(line, ";"));
strcpy(vec_question[index].question, strtok(NULL, ";"));
strcpy(vec_question[index].option1, strtok(NULL, ";"));
strcpy(vec_question[index].option2, strtok(NULL, ";"));
strcpy(vec_question[index].option3, strtok(NULL, ";"));
strcpy(vec_question[index].correct, strtok(NULL, ";"));
vec_question[index].correct[strlen(vec_question[index].correct) - 1] = '\0';
index++;
}
fclose(perguntas);
index = 20;
numaleat = rand() % index;
printf("%s : %s\n%s\n%s\n%s",vec_question[numaleat].category,vec_question[numaleat].question,vec_question[numaleat].option1,vec_question[numaleat].option2,vec_question[numaleat].option3);
for (int i = 0; i < num_users; i++) {
printf("\n%s: ", &users[i][20]);
scanf("%s", &answer[32]);
if (answer == vec_question[numaleat].correct)
userspoints[i] += 1;
}
}
}
In general one should assume that functions like strtok can fail.
Sometimes it fails and returns a NULL value. A short record in your input is a likely cause.
Consider using it with a loop, and breaking out of the loop once strtok returns NULL.
I found a simple example here.
#include <string.h>
#include <stdio.h>
int main () {
char str[80] = "This is - www.tutorialspoint.com - website";
const char s[2] = "-";
char *token;
/* get the first token */
token = strtok(str, s);
/* walk through other tokens */
while( token != NULL ) {
printf( " %s\n", token );
token = strtok(NULL, s);
}
return(0);
}
Note that it does one strtok to get the first token. That might return NULL in which case the loop doesn't run. If it doesn't return NULL then it prints that token, and asks strtok for the next token. It keeps doing that until strtok returns NULL.

why segmentation fault? strtok and malloc

I have the following code which works perfectly when not using malloc, but when I want to add in dynamic memory allocation it says segmentation fault although it compiles without warnings or errors. Why?
Thanks in advance
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXNUM 30
#define STR 200
#define MAXLEN 40
struct human { //Va
char name[MAXLEN];
char surname[MAXLEN];
int age;
float weight;
};
int main(int argc, char *argv[]) {
char *dlim= ",", *end = "\n", *stop = NULL;
char *tok, *string;
string = (char *)malloc(sizeof(char) * STR);
int i = 0, j = 0;
struct human man[MAXNUM];
FILE *fin = fopen("data.txt", "r");
if (string == NULL) {
printf("Memory not allocated");
}
if (fin == NULL) {
printf("Cannot open file\n");
exit(0);
}
while (fgets(string, sizeof(string), fin)) {
tok = strtok(string, dlim);
strcpy(man[i].name, tok);
tok = strtok(stop, dlim);
strcpy(man[i].surname,tok);
tok = strtok(stop, dlim);
man[i].age = atoi(tok);
tok = strtok(stop, dlim);
man[i].weight = atof(tok);
i++;
}
fclose(fin);
free(string);
j = i;
i = 0;
while (i < j) {
printf("%s %s %d %f \n", man[i].name, man[i].surname, man[i].age, man[i].weight);
i++;
}
return 0;
}
When you make string an allocated array of char, sizeof(string) no longer gives you the size of the array, it gives you the size of the pointer. Therefore you must change the loop to tell fgets the size of your array:
while (fgets(string, STR, fin)) {
...
Or better, if you reallocate the array to size size:
while (fgets(string, size, fin)) {
...

Segmentation Fault with strlen

I am getting a segmentation fault error. When I comment out "wordlength = strlen(token);" it runs fine. I don't know why it the seg fault happens when I assign a strlen(token) just fine to an int a few lines before this one. I would appreciate any help possible.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define char_max 60
int main(int argc, char *argv[])
{
FILE *fp = fopen(argv[2],"r");
char **wordlist;
int row = 1;
int i;
char temp[100];
char *token;
int wordlength;
int lengthcounter;
wordlist = (char**)malloc(row*sizeof(char*));
for(i = 0; i < row; i++)
{
wordlist[i] = (char*)malloc(char_max*sizeof(char*));
}
while(fgets(temp, sizeof(temp), fp) != NULL)
{
lengthcounter = 0;
wordlength = 0;
token = strtok(temp, " ");
strcat(wordlist[row-1], token);
printf("%s\n", wordlist[row-1]);
lengthcounter = strlen(token);
while(token != NULL)
{
token = strtok(NULL, " ");
wordlength = strlen(token);
/*lengthcounter += wordlength;*/
}
printf("The lengthcounter is %d\n", lengthcounter);
}
free(wordlist);
fclose(fp);
return 0;
}
while(token != NULL)
{
token = strtok(NULL, " ");
wordlength = strlen(token);
/*lengthcounter += wordlength;*/
}
What happens in the last iteration of the loop when token is NULL? You pass it to strlen anyway.
Also, this is almost certainly wrong:
wordlist[i] = (char*)malloc(char_max*sizeof(char*));
You're allocating space for pointers, not characters. So why sizeof(char*)? Also, don't cast the return value of malloc. This is C, not C++.

Resources