Currently working on a concordance program in C. When I try to run the program though, I get an error.
This is my C program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
void print(char Table, int n) {
printf("%d: ", n+1); // Prints the table
}
int insert(const void *bb, const void *cc) {
return strcmp(*(const char **)bb, *(const char **)cc);
}
void empty(char *Table[]) {
strcat(Table,"NULL"); // Empties the table
}
int main(int argc, char *argv[]){
if(argc!=3){
printf("ERROR: Usage: concordance table_size"); // Errors due to not enough variables (Should be tablesize and file name)
} else {
FILE *fp; //This block opens the file user has inputted and makes the string "File_contents" set to the file's contecnts
fp = fopen(argv[2],"r");
char *file_contents;
long input_file_size;
fseek(fp, 0, SEEK_END);
input_file_size = ftell(fp);
rewind(fp);
file_contents = malloc((input_file_size + 1) * (sizeof(char)));
fread(file_contents, sizeof(char), input_file_size, fp);
fclose(fp);
file_contents[input_file_size] = 0;
char *word, *words[strlen(file_contents)/2+1];
int i, n;
for(i=0;file_contents[i];i++){
file_contents[i]=tolower(file_contents[i]); //Converts all words to lower case
}
i=0;
word = strtok(file_contents, " ,.-:;?!"); //Chars which signal end of word
while(word != NULL) {
words[i++] = word;
word = strtok(NULL, " ,.-:;?!");
}
n = i;
qsort(words, n, sizeof(*words), insert);
for(i=0; i<n; ++i){
print(words[i],i);
printf("%s\n", words[i]);
}
empty(words);
fclose(fp); // Closes open file
}
return 0;
}
And the following is the error I'm getting:
* glibc detected * concordance: double free or corruption (!prev): 0x0000000001060f010
Not sure what could be causing this error to happen. Any help on this would be great though.
You aren't calling fclose() twice. Which I suppose in turn might call free() internally. Remove the fclose() at the end of the program.
you are passing NULL as argument to strtok function. I think this may cause the problem
Related
I have read a lot documentation about this subject but i still have some problem about this,ı know what pointer is but when i try to use ı am facing some problem ,at below code,txt file includes just one words at every line.I tried the read random line from text and return to main function cause after i will need this).And i print it in main function ,please can you help me which section should i change in this code?(When ı try to run this the error message is Segmentation fault (core dumped))
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
char word(char *file, char str[], int i);
int main() {
char buf[512];
char j = word("words.txt", buf, 512);
puts(j); // print random num
}
char word(char *file, char str[], int i) {
int end, loop, line;
FILE *fd = fopen(file, "r");
if (fd == NULL) {
printf("Failed to open file\n");
return -1;
}
srand(time(NULL));
line = rand() % 100 + 1; // take random num
for (end = loop = 0; loop < line; ++loop) {
if (0 == fgets(str, sizeof(str), fd)) { // assign text within a random line to STR
end = 1;
break;
}
}
if (!end)
return (char*)str; // return the str pointer
fclose(fd);
}
You reopened the file, this might be the case. You don't close the file if it returns in if(!end) part the fd is not closed.
And the function takes char but actually needs char *
char word(char *file, char str, int i);
int main() {
char * buf = malloc(sizeof(char)*512);
char *words = "words.txt";
char* j = word(words, buf, 512);
puts(j); // print random num
}
char word(char *file, char str[], int i) { // FIX HERE
int end, loop, line;
FILE *fd = fopen(file, "r"); //
if (fd == NULL) {
printf("Failed to open file\n");
return -1;
}
srand(time(NULL));
line = rand() % 100 + 1; // take random num
for (end = loop = 0; loop < line; ++loop) {
if (0 == fgets(str, sizeof(str), fd)) { // MAIN PROBLEM, PUT A CHAR* TO STR.
end = 1;
break;
}
}
fclose(fd); // YOU DIDN'T CLOSE IF IT RETURNED BEFORE
if (!end)
return str; // return the str pointer
//NOTHING IS RETURNED HERE
return str;
// I guess the problem is here, you return nothing and the function finishes, and you try to write that nothing with puts function which may cause a seg fault.
}```
I want to change my input.txt file to an integer array.
But sadly I keep missing one integer whenever new-line-character is met.
Following is my main()
int main(int args, char* argv[]) {
int *val;
char *STRING = readFile();
val = convert(STRING);
return 0;
}
Following is my file input function
char *readFile() {
int count;
FILE *fp;
fp = fopen("input.txt", "r");
if(fp==NULL) printf("File is NULL!n");
char* STRING;
char oneLine[255];
STRING = (char*)malloc(255);
assert(STRING!=NULL);
while(1){
fgets(oneLine, 255, fp);
count += strlen(oneLine);
STRING = (char*)realloc(STRING, count+1);
strcat(STRING, oneLine);
if(feof(fp)) break;
}
fclose(fp);
return STRING;
}
Following is my integer array function
int *convert(char *STRING){
int *intarr;
intarr = (int*)malloc(sizeof(int)*16);
int a=0;
char *ptr = strtok(STRING, " ");
while (ptr != NULL){
intarr[a] = atoi(ptr);
printf("number = %s\tindex = %d\n", ptr, a);
a++;
ptr = strtok(NULL, " ");
}
return intarr;
}
There are many issues.
This is a corrected version of your program, all comments are mine. Minimal error checking is done for brevity. intarr = malloc(sizeof(int) * 16); will be a problem if there are more than 16 numbers in the file, this should be handled somehow, for example by growing intarr with realloc, similar to what you're doing in readFile.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
char *readFile() {
FILE *fp;
fp = fopen("input.txt", "r");
if (fp == NULL)
{
printf("File is NULL!n");
return NULL; // abort if file could not be opened
}
#define MAXLINELENGTH 255 // define a constant rather than hardcoding "255" at several places
char* STRING;
char oneLine[MAXLINELENGTH];
STRING = malloc(MAXLINELENGTH);
int count = MAXLINELENGTH; // count mus be initialized and better declare it here
assert(STRING != NULL);
STRING[0] = 0; // memory pointed by STRING must be initialized
while (fgets(oneLine, MAXLINELENGTH, fp) != NULL) // correct usage of fgets
{
count += strlen(oneLine);
STRING = realloc(STRING, count + 1);
strcat(STRING, oneLine);
}
fclose(fp);
return STRING;
}
int *convert(char *STRING, int *nbofvalues) { // nbofvalues for returning the number of values
int *intarr;
intarr = malloc(sizeof(int) * 16);
int a = 0;
char *ptr = strtok(STRING, " \n"); // strings may be separated by '\n', or ' '
*nbofvalues = 0;
while (ptr != NULL) {
intarr[a] = atoi(ptr);
printf("number = %s\tindex = %d\n", ptr, a);
a++;
ptr = strtok(NULL, " \n"); // strings are separated by '\n' or ' '
} // read the fgets documentation which
// terminates read strings by \n
*nbofvalues = a; // return number of values
return intarr;
}
int main(int args, char* argv[]) {
int *val;
char *STRING = readFile();
if (STRING == NULL)
{
printf("readFile() problem\n"); // abort if file could not be read
return 1;
}
int nbvalues;
val = convert(STRING, &nbvalues); // nbvalues contains the number of values
// print numbers
for (int i = 0; i < nbvalues; i++)
{
printf("%d: %d\n", i, val[i]);
}
free(val); // free memory
free(STRING); // free memory
return 0;
}
I'm not sure what your requirement is, but this can be simplified a lot because there is no need to read the file into memory and then convert the strings into number. You could convert the numbers on the fly as you read them. And as already mentioned in a comment, calling realloc for each line is inefficient. There is room for more improvements.
I have an archive results.csv and I need to read the first line of this archive and print it out on output.txt. Somehow it's printing random characters after everything and I couldn't figure out what is wrong.
Command: a.c results.csv
First line:
date,home_team,away_team,home_score,away_score,tournament,city,country,neutral
output.txt: date,home_team,away_team,home_score,away_score,tournament,city,country,neutral,(!£,(!£,(!£,(!£,(!£,#,£,(!£,(!£
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
typedef struct
{
char *line1;
char *line1a;
char *line1b;
char *team1;
char *team2;
char *reason;
char *city;
char *country;
char *neutral_field;
}data;
void open_input(char *argv[], FILE **input)
{
if((*input=fopen(argv[1], "r")) == NULL)
{
printf("%s not found\n", argv[1]);
exit(1);
}
}
void open_output(char *string, FILE **output)
{
if((*output=fopen(string, "w")) == NULL)
{
printf("%s not found\n", string);
exit(1);
}
}
void alloc_data(data *d, int size)
{
d->line1 = (char*)malloc(4*sizeof(char));
d->team1 = (char*)malloc(9*sizeof(char));
d->team2 = (char*)malloc(9*sizeof(char));
d->line1a = (char*)malloc(10*sizeof(char));
d->line1b = (char*)malloc(10*sizeof(char));
d->reason = (char*)malloc(10*sizeof(char));
d->city = (char*)malloc(4*sizeof(char));
d->country = (char*)malloc(7*sizeof(char));
d->neutral_field = (char*)malloc(7*sizeof(char));
}
void store(data *d, FILE *input, FILE **output)
{
fscanf(input, "%s,%s,%s,%s,%s,%s,%s,%s,%s", d[0].line1, d[0].team1, d[0].team2, d[0].line1a, d[0].line1b, d[0].reason, d[0].city, d[0].country, d[0].neutral_field );
fprintf(*output, "%s,%s,%s,%s,%s,%s,%s,%s,%s\n", d[0].line1, d[0].team1, d[0].team2, d[0].line1a, d[0].line1b, d[0].reason, d[0].city, d[0].country, d[0].neutral_field );
}
int main(int argc, char *argv[])
{
FILE *input;
FILE *output;
char *string = "output.txt";
int size = 1000;
open_input(argv, &input);
open_output(string, &output);
data *d;
d = (data*)malloc(size*sizeof(data));
alloc_data(d, size);
store(d, input, &output);
free(d);
return 0;
}
fscanf(input, "%s,%s,%s,%s,%s,%s,%s,%s,%s", d[0].line1, d[0].team1,...
The above code tries to read the whole line in to d[0].line1 which causes buffer overflow. team1 and the rest will contain uninitialized data.
You have to change fscanf as follows:
fscanf(input, "%3[^ ,\n\t],%9[^ ,\n\t],...
Where 3 is 4 - 1, and 4 is the size of d[0].line1
Alternatively you can use strtok
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void store(FILE *input, FILE *output)
{
char buf[500];
while(fgets(buf, sizeof(buf), input))
{
//strip end-of-line from `buf`
if(strlen(buf))
if(buf[strlen(buf) - 1] == '\n')
buf[strlen(buf) - 1] = 0;
//tokenize with strtok
char *token = strtok(buf, ",");
while(token)
{
fprintf(output, "%s", token);
token = strtok(NULL, ",");
}
fprintf(output, "\n");
}
}
int main(int argc, char *argv[])
{
FILE *input = fopen("input.txt", "r");
FILE *output = fopen("output.txt", "w");
store(input, output);
return 0;
}
With above code you don't need an additional structure.
If you do use a structure for data, you have to be more careful. It seems you are trying to create an array of 1000 data, but the following only creates one oversized pointer, not an array of data
int size = 1000;
data *d;
d = (data*)malloc(size*sizeof(data));
alloc_data(d, size);
Additionally, for each malloc there should be a corresponding free.
Your buffers aren't big enough to hold the terminating NUL byte. scanf stores that NUL byte (overrunning the buffer), but then the object that really owns that byte may overwrite it, so when printf looks for the NUL it doesn't find it until much later in memory.
The buffer overruns are a bigger problem than what you've seen, who knows what objects those NUL bytes you didn't make space for are smashing? And what happens when you read a data file with slightly different header spelling? Suddenly your hard-coded allocations sizes will be even more wrong than they are already.
I want to xor a certain value on all of my chars in a char array. I have some code that works all fine except for the xor line:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void obfuscate(FILE *file, char *input, char *variableName)
{
int i;
int size = (int)strlen(input);
char a = 65;
fprintf(file, "%s: %s -> ", variableName, input);
for(i = 0; i < size; i++)
{
input[i] = (char)(input[i] ^ a);//I am causing a segmentation fault
fprintf(file, "0x%x, ", input[i]);
}
return;
}
int main()
{
char *a = "MyString";
FILE *file = fopen("out.txt", "w");
obfuscate(file, a, "a");
fclose(file);
}
I use the normal gcc compiler with gcc in.c -o out.o on a linux machine.
If I comment the line with the xor operation it works just fine. Any help is highly appreciated, my own research did not result in a solution.
Try below solution with dynamic memory.
In char *a = "MyString"; char *in = malloc(sizeof(a));
a is pointing to code section we can't alter it. &
in is pointing to heap section, so we can modify it any no.of times.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void obfuscate(FILE *file, char *input, char *variableName)
{
int i;
int size = (int)strlen(input);
char a = 65;
fprintf(file, "%s: %s -> ", variableName, input);
for(i = 0; i < size; i++)
{
input[i] = (char)(input[i] ^ a);//I am causing a segmentation fault
fprintf(file, "0x%x, ", input[i]);
}
return;
}
int main()
{
char *a = "MyString";
char *in = malloc(sizeof(a));
strcpy(in, a);
FILE *file = fopen("out.txt", "w");
obfuscate(file, in, "a");
fclose(file);
free(in);
}
I am a beginner in C programming, and I am trying to write a simple code to read a text file and write its content into an array, then print it on console. However, I always get 0.0000, and I could not solve the problem.
#include <stdio.h>
#include <stdlib.h>
int numOfLines(FILE *fp1);
void printarr(float arr[], int size);
float *filetoArr(FILE *fp, int arrsize);
int main(int argc, const char *argv[]) {
char *fileName1 = argv[1];
FILE *fp1 = fopen(fileName1, "r");
printf("File name: %s", fileName1);
int size = numOfLines(fp1);
printf("Number of lines in the file: %d\n", size);
float *arr = filetoArr(fp1, size);
printarr(arr, size);
free(arr);
fclose(fp1);
}
void printarr(float *arr, int size) {
for (int i = 0; i < size; i++) {
printf("%f ", *(arr + i));
}
}
float *filetoArr(FILE *fp, int arrsize) {
int size = arrsize;
float *arr = (float *)malloc(sizeof(float) * size);
for (int i = 0; i < size; i++) {
fscanf(fp, "%f\n", (arr+i));
}
return (arr);
}
int numOfLines(FILE *fp1) {
int numberOfLines = 0;
char c;
do {
c = getc(fp1);
if (c == '\n') {
numberOfLines++;
}
} while (c != EOF);
return numberOfLines;
}
your numOfLines goes to the end of the file.
You have to rewind(fp1) to reset your file handle to position 0, or fscanf hits the end of the file, and doesn't read anything (check return code from fscanf: it should be 1 I bet you're getting 0 all the time)
There are multiple problems in your code:
you read the whole file in numOfLines(): you must reset the file pointer to the beginning of file with rewind(fp1); so fscanf() can read the file instead of hitting the end of file immediately.
the variable c used to read bytes from the file must be defined as an int for the test for end of file to be reliable. Otherwise, depending on whether char is signed or not by default, the EOF would never match or could potentially match the character \377 as end of file erroneously.
you do not check for failure to open the file.
Although returning 0 is implicit for function main() since C99, it is advisable to write the return 0; statement explicitly for better clarity.