Stack smashing in file io in c - c

void issueBook(){
printf("Hii!\n");
//printf("Enter your student ID: ");
//int stdID;
//scanf("%d", &stdID);
printf("Enter the book ID\n");
int bookID;
scanf("%d", &bookID);
FILE *in_file = fopen("recordLib.txt", "r");
FILE *fp = fopen("temp.txt", "w");
struct stat sb;
stat("recordLib.txt", &sb);
char *file_contents = malloc(1024);
int mark = 0;
char ID[] = "";
while (fscanf(in_file, "%[^\n] ", file_contents) != EOF) {
int size = strlen(file_contents);
int countCom = 0;
char ID[] = "";
//printf("%d\n", size);
if(mark == 0){
for(int i=0; i<size; i++){
//printf("asdfsd\n");
//printf("%c", file_contents[i]);
if(countCom == 0 && (file_contents[i] != ',')){
strncat(ID, &file_contents[i], 1);
//printf("%c\n", file_contents[i]);
}
else if(atoi(ID) != bookID){
break;
}
else if((file_contents[i] == ',') && (countCom < 3) && (atoi(ID) == bookID)){
//printf("%c\n", file_contents[i]);
//printf("%s\n", ID);
countCom++;
}
else{
//printf("%c\n", file_contents[i]);
if(file_contents[i] == '1'){
printf("Sorry!! someone has already issued the book");
mark = 2;
break;
}
else if(file_contents[i] == '0'){
file_contents[i] = '1';
mark = 1;
break;
}
}
}
}
fwrite(file_contents, 1, size, fp);
fwrite("\n", 1, 1, fp);
}
fclose(fp);
fclose(in_file);
remove("recordLib.txt");
rename("temp.txt", "recordLib.txt");
//printf("%d\n", s);
//if(mark == 1){
// updateStu();
//}
free(file_contents);
}
I have made this function which takes the bookID from the user and then searches for it in the file:
Searching: It reads line by line and as we already know till first comma ',' it would be book ID so it will store in another string and then convert it to int. Now it will compare it with entered ID if it matches then it will update the 0 at the end to 1, else move to next line.
Error: I always getting stack smashing error when the function again returns to the main function. I am unable to find the thing that is causing the error. Also that when I run in VS code, it runs successfully but in Linux this problem occurs! Please help. Thanks in advance.

Related

Results from string search not printing to console as expected

So I have this code which I was working on. The goal is to search for a string in a file and when that string is found it would return the corresponding values in that section of the file. So this is the file in question that is being searched:
So if it finds "AJ" then it would return all the values right up to "22550" and if it finds "TS" then it prints everything after "TS" and after "60500." This is my code in question:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
char *name;
char *code;
int grpsize;
char route;
char *package;
//float fee;
float tcost;
float fcost;
} bookingrecord;
int main() {
FILE *fptr;
bookingrecord bookingrec;
char book_code[5];
printf("\n Please enter the code that corressponds to your record: ");
scanf("%s", book_code);
fptr = fopen("bookingdata", "r");
if (fptr == NULL) {
printf ("\nSorry we didn't find your file.");
exit (1);
}
ssize_t read;
char * line = NULL;
size_t len = 0;
int count = 0;
int found = 0;
while ((read = getline(&line, &len, fptr)) != -1) {
if (count == 0) {
bookingrec.code = line;
//printf("%s %s",bookingrec.code,book_code);
if (strcmp(bookingrec.code, book_code) == 0) {
found = 1;
}
} else if (count == 1 && found == 1) {
bookingrec.grpsize = line;
} else if (count == 2 && found == 1) {
bookingrec.route = line;
} else if (count == 3 && found == 1) {
bookingrec.fcost = strtof(line, NULL);
} else if (count == 4 && found == 1) {
bookingrec.name = line;
} else if (count == 5 && found == 1) {
bookingrec.package = line;
} else if (count == 6 && found == 1) {
bookingrec.tcost = strtof(line, NULL);
}
count = count + 1;
if(strlen(line) == 0) {
count = 0;
}
}
if (found == 1) {
printf("\n We have found your file");
printf("\n %s", bookingrec.code);
printf("\n %s", bookingrec.name);
printf("\n %d", bookingrec.grpsize);
printf("\n %s", bookingrec.route);
printf("\n %c", bookingrec.package);
printf("\n %.2f", bookingrec.tcost);
printf("\n %.2f", bookingrec.fcost);
}
fclose(fptr);
return 0;
}
The problem is that it only gives me this as the result:
So it finds the file okay but nothing happens so I uncomment a printf which I added to troubleshoot a bit right above my strcmp and get this when I enter for eg. "AJ":
I try another of the two character string. "SH" in this case and get this:
So it seems as if it is accepting any of the codes but prints the first line twice? But also discards everything else. I am a bit stumped as to what is happening. Any ideas?
Update:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
char *name;
char *code;
int grpsize;
char *route;
char *package;
//float fee;
float tcost;
float fcost;
} bookingrecord;
int main() {
FILE *fptr;
bookingrecord bookingrec;
char book_code[5];
printf("\n Please enter the code that corressponds to your record: ");
scanf("%s", book_code);
fptr = fopen("bookingdata", "r");
if (fptr == NULL) {
printf ("\nSorry we didn't find your file.");
exit (1);
}
ssize_t read;
char * line = NULL;
size_t len = 0;
int count = 0;
int found = 0;
while ((read = getline(&line, &len, fptr)) != -1) {
line[strcspn(line, "\r\n")] = 0; //trims getLine
//printf("line is %s, count is %d \n", line, count);//debugging
if (count == 0) {
bookingrec.code = strdup(line);
if (strcmp(bookingrec.code, book_code) == 0) {
found = 1;
}
} else if (count == 1 && found == 1) {
char *tmp;
bookingrec.grpsize = strtol(strdup(line), NULL, 10);
} else if (count == 2 && found == 1) {
bookingrec.route = strdup(line);
} else if (count == 3 && found == 1) {
bookingrec.fcost = strtof(strdup(line), NULL);
} else if (count == 4 && found == 1) {
bookingrec.name = strdup(line);
} else if (count == 5 && found == 1) {
bookingrec.package = strdup(line);
} else if (count == 6 && found == 1) {
bookingrec.tcost = strtof(strdup(line), NULL);
}
count = count + 1;
if (found == 1 && count == 7){
break;
}
if(strlen(line) == 0) {
count = 0;
}
}
if (found == 1) {
printf("\n We have found your file");
printf("\n %s", bookingrec.code);
printf("\n %s", bookingrec.name);
printf("\n %d", bookingrec.grpsize);
printf("\n %s", bookingrec.route);
printf("\n %s", bookingrec.package);
printf("\n %.2f", bookingrec.tcost);
printf("\n %.2f", bookingrec.fcost);
}
fclose(fptr);
return 0;
}
Updated screens after edits:

How can I input a word, read through a dictionary, and print the word's translation?

My objective is to input a string "sana" which will at the end print only one corresponding result. Ie: if I enter the word "sana" it would print "Word sana is in English word" and if the user enters "word" it prints "Word word is in Finnish sana". So the code is not working at all so I wanted to ask how should I continue. if-else doesn't work at all but I thought it would help me visualize where to go there.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
Read file line by line
split lines using ; as delimiter
store first/second part in some array
ask user to input and search the word in that array
*/
int main()
{
FILE *fp;
char sana[30];
char *p;
void *tmp;
int lasku = 0;
int pal = 1;
int i;
char **vars = NULL;
char **vals = NULL;
fp = fopen("dictionary.txt", "r");
printf("Word: ");
scanf("%s", sana);
while (fgets(sana, sizeof(sana), fp)) {
sana[strcspn(sana, "\n")] = 0;
if (!(p = strchr(sana, ';')))
continue;
*p++ = 0; //poistaa ;
if (!strlen(sana) || !strlen(p))
continue;
if (!(tmp = realloc(vars, (lasku + 1) * sizeof(char*))))
goto out;
vars = (char**)tmp;
if (!(tmp = realloc(vals, (lasku + 1) * sizeof(char*))))
goto out;
vals = (char**)tmp;
vars[lasku] = strdup(sana);
vals[lasku] = strdup(p);
lasku++;
if (!vars[lasku-1] || ! vals[lasku-1])
goto out;
}
pal = 0;
if (i == 0 || i == 2 || i == 4)
printf("Word %s is in English %s\n", vars[i], vals[i]);
else
if (i == 1 || i == 3 || i == 5)
printf("Word %s is in Finnish %s\n", vals[i], vars[i]);
else
printf("Word can't be found in the dictionary");
out:
fclose(fp);
if (vars)
for (i = 0; i < lasku; i++)
free(vars[i]);
if (vals)
for (i = 0; i < lasku; i++)
free(vals[i]);
free(vars);
free(vals);
return pal;
}
The code does not work because:
you overwrite the word in sana when you read the dictionary.
you never set i.
testing the value of uninitialized variable i has undefined behavior.
You should first local the dictionary in memory, then read words from the user and search them in the dictionary for matches.
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
Read file line by line
split lines using ; as delimiter
store first/second part in some array
ask user to input and search the word in that array
*/
int main() {
FILE *fp;
char sana[30];
char **tmp;
int lasku = 0, i, found, error = 0;
char **vars = NULL;
char **vals = NULL;
fp = fopen("dictionary.txt", "r");
while (fgets(sana, sizeof(sana), fp)) {
sana[strcspn(sana, "\n")] = '\0';
if (!(p = strchr(sana, ';')))
continue;
*p++ = '\0';
if (!*sana || !*p)
continue;
if (!(tmp = realloc(vars, (lasku + 1) * sizeof(*vars)))) {
error = 1;
break;
}
vars = tmp;
if (!(tmp = realloc(vals, (lasku + 1) * sizeof(*vals)))) {
error = 1;
break;
}
vals = tmp;
vars[lasku] = strdup(sana);
vals[lasku] = strdup(p);
lasku++;
if (!vars[lasku-1] || !vals[lasku-1]) {
error = 1;
break;
}
}
fclose(fp);
if (!error) {
for (;;) {
printf("Word: ");
if (scanf("%29s", sana) != 1)
break;
found = 0;
for (i = 0; i < lasku; i++) {
if (!strcmp(sana, vars[i]) {
printf("Word %s is in English %s\n", vars[i], vals[i]);
found = 1;
}
if (!strcmp(sana, vals[i]) {
printf("Word %s is in Finnish %s\n", vals[i], vars[i]);
found = 1;
}
}
if (!found) {
printf("Word can't be found in the dictionary");
}
}
}
for (i = 0; i < lasku; i++) {
free(vars[i]);
free(vals[i]);
}
free(vars);
free(vals);
return error;
}

Not Getting Output in File

#include <stdio.h>
int main()
{
FILE *f1;
int ch, i, n = 0;
char q[500], opt[4][100];
int corAns;
f1 = fopen("C://Users//Lenovo//Desktop//fileInC1.txt", "a+");
if (f1 == NULL)
{
printf("Error Opening File.");
return 0;
}
else
{
while (n != 2)
{
n++;
printf("\nQuestion: ");
fgets(q, 500, stdin);
for (i = 0; i < 4; i++)
{
printf("\nOption %d: ", i + 1);
fgets(opt[i], 100, stdin);
}
printf("\nCorrect answer: ");
scanf("%d", corAns);
//program terminating here after only one iteration
fprintf(f1, "{\nQ: \"%s\", \n\topt: [\"%s\", \"%s\", \"%s\", \"%s\"], \n\tCA: %d }", q, opt[0], opt[1], opt[2], opt[3], corAns);
printf("\nData Written Successfully.");
}
}
fclose(f1);
return 0;
}
I have been trying to create a Javascript generator as you can see in the code.
The main problem i am getting is inside the while loop.
The while loop is terminating after only one iteration and the program not writting the data in the created file. The file already exists.
I am not getting where is the problem occuring.
You need to cleanse your input of new-lines. You also had a redundant Else statement, and Scanf requires the address of a variable, not it's value.
This should work for you. You can check out this question here: Fgets skipping inputs, which I shamelessly copied.
#include <stdio.h>
#include <string.h>
int main()
{
FILE *f1;
int ch, i, n = 0;
char q[500], opt[4][100];
int corAns;
int c;
char *p;
f1 = fopen("fileInC1.txt", "a+");
if (f1 == NULL)
{
printf("Error Opening File.");
return 0;
}
while (n != 2)
{
n++;
printf("\nQuestion: ");
fgets(q, 500, stdin);
if ((p=strchr(q, '\n')) != NULL) *p = '\0';
for (i = 0; i < 4; i++)
{
printf("\nOption %d: ", i + 1);
fgets(opt[i], 100, stdin);
if ((p=strchr(opt[i], '\n')) != NULL) *p = '\0';
}
printf("\nCorrect answer: ");
scanf("%d", &corAns);
//program terminating here after only one iteration
fprintf(f1, "{\nQ: \"%s\", \n\topt: [\"%s\", \"%s\", \"%s\", \"%s\"], \n\tCA: %d }", q, opt[0], opt[1], opt[2], opt[3], corAns);
printf("\nData Written Successfully.");
while ( (c = getchar()) != '\n' && c != EOF );
}
fclose(f1);
return 0;
}

C problem with saving structure to text file and downloading it back to stdout

Hey I have a problem with my code project where I try to create a project that keeps up wit Olympic medals. I have a problem of creating a text file that contains the structure and is named by user. I also have a problem to download the structure.
PROBLEM: I have a problem to make a text file named by user that contains the structure and then download it back to stdout. I don't know how to fix my functions to do this correctly. Now my function save_file can't even produce the file.
Example if the input:
A Canada
A USA
M USA 2 1 1
M Canada 0 0 1
M USA 1 3 1
M USA -1 0 0
L
W medals
Q
I have defined my structure this way:
typedef struct Olympia
{
char* country;
int gold;
int silver;
int bronze;
}Olympia;
Then I have a function that adds country
int add_country(struct Olympia* data, char* str, int i)
{
if (str[0] == '\0') //checking that input is correct
{
printf("Error! Try again!\n");
}
else
{
data[i].country = malloc(strlen(str) + 2); //allocating memory for country name
strcpy(data[i].country, str); //adding country to database
data[i].gold = 0; //setting medals to zero
data[i].silver = 0;
data[i].bronze = 0;
i++;
}
return i;
}
Next I add medals to the each country
int update_medals(struct Olympia* data, char* str, int add_gold, int add_silver, int add_bronze, int i)
{
int a = 0;
int b = 0;
if (str[0] == '\0') //checking that input is correct
{
printf("Error! Try again!");
}
else
{
while (a < i)
{
if (strcmp(data[a].country, str) == 0) //adding medals to right country
{
data[a].gold = data[a].gold + add_gold;
data[a].silver = data[a].silver + add_silver;
data[a].bronze = data[a].bronze + add_bronze;
b++;
}
a++;
}
if (b == 0) //and if the country didn't participate to the olympics
{
printf("This country isn't in the Olympics! Try Again!\n");
}
}
}
Next there is print function
int print_data(struct Olympia* data, int i)
{
for (int a = 0; a < i; a++)
{
printf("%s %d %d %d\n", data[a].country, data[a].gold, data[a].silver, data[a].bronze);
}
}
And then there are the two function that doesn't work. What should I do?
Olympia *save_file(Olympia* data, const char* filename, int i)
{
if (strlen(filename) > 100)
{
printf("Filename is too long: Maxium lenght for filename is 100 characters");
return data;
}
char name[100];
int ret = sscanf(filename, "W %s", name);
if (ret != 1)
{
printf("Error! Try again!");
return data;
}
FILE* file = fopen(name, "w");
if (!file)
{
printf("Error saving file! Try again");
return data;
}
int a = 0;
while (data[a].country[0] != 0)
{
fprintf(file, "%s %d %d %d\n", data[a].country, data[a].gold, data[a].silver, data[a].bronze);
a++;
}
fclose(file);
return 0;
}
int load_file(struct Olympia* data, char* filename, int i)
{
int a = 0;
FILE* file = fopen(filename, "r");
if (!file)
{
printf("Error opening file! Try again");
}
struct Olympia* arr = malloc(sizeof(Olympia));
while (fscanf(file, "%s %d %d %d", data[a].country, data[a].gold, data[a].silver, data[a].bronze))
{
i++;
a++;
arr = realloc(arr, sizeof(Olympia) * (i + 2));
}
arr[a].country[0] = 0;
fclose(file);
return arr;
}
And the main function
int main(void)
{
char command;
int gold = 0;
int silver = 0;
int bronze = 0;
int i = 0;
char* line = (char*)malloc((100) * sizeof(char)); //allocating memory for one stdin line
char* countryname = (char*)malloc(20 * sizeof(char)); // allocating memory for country name
char* filename = (char*)malloc(100 * sizeof(char));
struct Olympia* countrydata = malloc(sizeof(struct Olympia) * 1); //allocating memory for structure
line = fgets(line, 100, stdin);
while(1)
{
sscanf(line, "%c %s %d %d %d", &command, countryname, &gold, &silver, &bronze);
switch (command)
{
case 'A':
i = add_country(countrydata, countryname, i);
countrydata = realloc(countrydata, sizeof(struct Olympia) * (i + 1));
break;
case 'M':
update_medals(countrydata, countryname, gold, silver, bronze, i);
break;
case 'L':
print_data(countrydata, i);
break;
case 'W':
save_file(countrydata, filename, i);
break;
case 'O':
i = load_file(countrydata,filename, i);
break;
case 'Q':
free(line);
free(countryname);
free(countrydata);
return(EXIT_SUCCESS);
}
line = fgets(line, 100, stdin);
if (line == NULL)
{
free(line);
free(countryname);
free(countrydata);
return(EXIT_SUCCESS);
}
}
}
You call save_file(countrydata, filename, i); without having set filename. Change to save_file(countrydata, line, i); since for whatever reason you expect the command character W to precede the name.
Then in save_file() the condition in while (data[a].country[0] != 0) is unusable, since the data element after the last one is not initialized. Use while (a < i) instead.

C programming, clearing a string

So I have some code that gets a user input and compares it in a loop, it will check the first line, then the second, then the third and so on, however the program doesn't get another clean string variable for the next cycle of the loop, as shown here:
char text[100], blank[100];
int c = 0, d = 0;
void space(void);
int main()
{
int loop=0;
char str[512];
char string[512];
int line=1;
int dis=1;
int score=0;
char text[64];
FILE *fd;
fd = fopen("Student Usernames.txt", "r"); //Should be test
if (fd == NULL)
{
printf("Failed to open file\n");
exit(1);
}
do
{
printf("Enter the string: ");
gets(text);
while (text[c] != '\0')
{
if (!(text[c] == ' ' && text[c] == ' ')) {
string[d] = text[c];
d++;
}
c++;
}
blank[d] = '\0';
printf("Text after removing blanks\n%s\n", string);
getch();
for(loop = 0;loop<line;++loop)
{
fgets(str, sizeof(str), fd);
}
printf("\nLine %d: %s\n", dis, str);
dis=dis+1;
str[strlen(str)-1] = '\0';
if(strcmp(string,str) == 0 )
{
printf("Match\n");
score=score+2;
}
else
{
printf("Nope\n");
score=score+1;
}
getch();
}
while(!feof(fd));
printf("Score: %d",score);
getch();
}
For example: Input: Apple (1st word) , 1st line = Apple, Match, Input: Banana, 2nd line = Applea
Clearly the program has added onto to first input, I want to know how to change this
Edit: Upon reseting c and d back to 0 after each loop the output is now "AppleBanana"

Resources