Segmentation fault in C while iterating through array - c

I am trying to mimic a basic encryption algorithm. I try to read the encrypted data file and look for each corresponding value in a JRB tree (simple key-value pair in my case) which is basically filled from the ".key" file and then write it to another file.
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "fields.h"
#include <cJSON.h>
#include "jrb.h"
void decrypt();
int main(int argc, char **argv)
{
decrypt();
return 0;
}
void decrypt()
{
IS is_input;
FILE *fp;
int i, j;
char *buffer = 0;
char *str = 0;
long length;
FILE *f = fopen ("data/.key", "rb");
cJSON *json;
JRB b, tmp;
b = make_jrb();
tmp = make_jrb();
is_input = new_inputstruct("data/encrypted");
if (is_input == NULL) {
perror("Error: ");
exit(1);
}
fp = fopen("data/decrypted.txt", "w+");
if (fp < 0) { perror("Error: "); exit(1); }
if (f)
{
fseek (f, 0, SEEK_END);
length = ftell (f);
fseek (f, 0, SEEK_SET);
buffer = malloc (length);
if (buffer)
{
fread (buffer, 1, length, f);
}
fclose (f);
}
if (buffer)
{
json = cJSON_Parse(buffer);
cJSON *current_element = NULL;
char *current_key = NULL;
cJSON_ArrayForEach(current_element, json)
{
current_key = current_element->string;
if (current_key != NULL)
{
(void) jrb_insert_str(b, strdup(current_element->valuestring), new_jval_v(current_key));
}
}
while(get_line(is_input) >= 0) {
for (i = 0; i < is_input->NF; i++) {
str = is_input->fields[i];
tmp = jrb_find_str(b, "10001011"); // This works but when I use "str" here instead of "10001011", I get a segmentation fault.
// tmp = jrb_find_str(b, str);
fprintf(fp, "%s ", tmp->val.s);
}
}
}
jettison_inputstruct(is_input);
fclose(fp);
return;
}
The .key file is like this:
{
"hi": "0",
"merhaba": "10",
"hallo": "11"
}
After running the program with printf I get a Segmentation fault after printing it is data like this:
0 10 11Segmentation fault (core dumped)
But if I try to use fprintf to write it into another file I directly get the Segmentation fault error.
I tried to debug and I see that the tmp value is null but how can it be null?
About JRB: http://web.eecs.utk.edu/~jplank/plank/classes/cs360/360/notes/JRB/index.html
Input struct:
const char *name; /* File name */
FILE *f; /* File descriptor */
int line; /* Line number */
char text1[MAXLEN]; /* The line */
char text2[MAXLEN]; /* Working -- contains fields */
int NF; /* Number of fields */
char *fields[MAXFIELDS]; /* Pointers to fields */
int file; /* 1 for file, 0 for popen */

Related

string of undetermined length c

Hi I was trying to create an array of string of an undetermined length in c.
This is my code :
int main()
{
int lineCount=linesCount();
char text[lineCount][10];
printf("%d",lineCount);
FILE * fpointer = fopen("test.txt","r");
fgets(text,10,fpointer);
fclose(fpointer);
printf("%s",text);
return 0;
}
I would like to replace 10 in
char text[lineCount][10];
My code reads out a file I already made the amount of lines dynamic.
Since the line length is unpredictable I would like to replace 10 by a something dynamic.
Thanks in advance.
To do this cleanly, we want a char * array rather than an 2D char array:
char *text[lineCount];
And, we need to use memory from the heap to store the individual lines.
Also, don't "hardwire" so called "magic" numbers like 10. Use an enum or #define (e.g) #define MAXWID 10. Note that with the solution below, we obviate the need for using the magic number at all.
Also, note the use of sizeof(buf) below instead of a magic number.
And, we want [separate] loops when reading and printing.
Anyway, here's the refactored code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
linesCount(void)
{
return 23;
}
int
main(void)
{
int lineCount = linesCount();
char *text[lineCount];
char buf[10000];
printf("%d", lineCount);
// open file and _check_ the return
const char *file = "test.txt";
FILE *fpointer = fopen(file, "r");
if (fpointer == NULL) {
perror(file);
exit(1);
}
int i = 0;
while (fgets(buf, sizeof(buf), fpointer) != NULL) {
// strip newline
buf[strcspn(buf,"\n")] = 0;
// store line -- we must allocate this
text[i++] = strdup(buf);
}
fclose(fpointer);
for (i = 0; i < lineCount; ++i)
printf("%s\n", text[i]);
return 0;
}
UPDATE:
The above code is derived from your original code. But, it assumes that the linesCount function can predict the number of lines. And, it doesn't check against overflow of the fixed length text array.
Here is a more generalized version that will allow an arbitrary number of lines with varying line lengths:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
main(void)
{
int lineCount = 0;
char **text = NULL;
char buf[10000];
// open file and _check_ the return
const char *file = "test.txt";
FILE *fpointer = fopen(file, "r");
if (fpointer == NULL) {
perror(file);
exit(1);
}
int i = 0;
while (fgets(buf, sizeof(buf), fpointer) != NULL) {
// strip newline
buf[strcspn(buf,"\n")] = 0;
++lineCount;
// increase number of lines in array
text = realloc(text,sizeof(*text) * lineCount);
if (text == NULL) {
perror("realloc");
exit(1);
}
// store line -- we must allocate this
text[lineCount - 1] = strdup(buf);
}
fclose(fpointer);
// print the lines
for (i = 0; i < lineCount; ++i)
printf("%s\n", text[i]);
// more processing ...
// free the lines
for (i = 0; i < lineCount; ++i)
free(text[i]);
// free the list of lines
free(text);
return 0;
}

Reading data from file into structure in c programming language

I want to read data from txt file and save those data in variables not just print output. How do I save those data from text file in variables?
I tried like this and it did not work out:
int value1 ;
object2->value =&value1 ;
*(object2->value) = value1 ;
My txt file looks like this:
INT
A
5
and my code looks like this:
#include <stdio.h>
#include <stdlib.h> // For exit()
struct variable {
char type[10];
char name[10];
int value;
};
int main(){
struct variable *object2=malloc(sizeof(struct variable));
FILE * file= fopen("input.txt", "rb");
if (file != NULL) {
fread(object2, sizeof(struct variable), 1, file);
fclose(file);
}
int value1 ;
object2->value =&value1 ;
*(object2->value) = value1 ;
printf("%d\n",value1);
printf("%s/%s/%d\n",object2->type,object2->name,object2->value);
}
File format:
CHAR
B
6
INT
A
5
FLOAT
C
7
This is my solution:
#include <stdio.h>
#include <stdlib.h> // For exit()
#include <string.h>
#define BUFF_SIZE 1024
#define NAME_TYPE_SIZE 10
#define VALUE_SIZE 20
#define NOT_ENOUGH_MEMORY 1
#define CANT_OPEN_FILE 2
#define FILE_ENDED 3
#define TOO_BIG_STR 4
#define CANT_FORMAT_VALUE 5
#define NOT_FOUND_LINE 6
#define SEARCH_NAME "A"
#pragma warning(disable : 4996) // for vs
struct variable {
char type[NAME_TYPE_SIZE];
char name[NAME_TYPE_SIZE];
int value;
};
int find_var_in_file(char* file_path, char* find_name, struct variable* dest);
int main()
{
struct variable* object2 = malloc(sizeof(struct variable));
if (NULL == object2)
{
printf("not enough memory");
return NOT_ENOUGH_MEMORY;
}
int error = find_var_in_file("input.txt", SEARCH_NAME, object2);
if (CANT_OPEN_FILE == error)
{
return printf("can't open file");
}
if (error == 0)
{
// Printing data to check validity
printf("read: type: %s name: %s value: %d", object2->type, object2->name, object2->value);
int a = object2->value;
// do stuff with a
}
else
{
if (error == NOT_FOUND_LINE)
{
printf("not find the var \"" SEARCH_NAME "\" in the file");
}
else
{
printf("error reading the file. error code: %d", error);
}
}
free(object2);
return 0;
}
int read_line(char* buffer, int buffer_size, char* dest, int dest_size, FILE* stream)
{
if (!fgets(buffer, buffer_size, stream))
{
return NOT_FOUND_LINE;
}
int read_len = strlen(buffer);
if ('\n' == buffer[read_len - 1])
{
if (read_len == 1)
{
return NOT_FOUND_LINE;
}
buffer[read_len - 1] = '\0'; // remove "\n" in the end
}
if (dest_size <= strlen(buffer)) // last chat is null
{
return TOO_BIG_STR;
}
strcpy(dest, buffer);
// clear the read
memset(buffer, '\0', read_len);
return 0;
}
int find_var_in_file(char* file_path, char* find_name, struct variable* dest)
{
char file_buffer[BUFF_SIZE] = { 0 }; // Buffer to store data
FILE* stream = fopen(file_path, "r");
if (NULL == stream)
{
return CANT_OPEN_FILE;
}
int error = 0;
while (1)
{
// read type
int read_type_result = read_line(file_buffer, BUFF_SIZE, dest->type, NAME_TYPE_SIZE, stream);
if (read_type_result != 0)
{
error = read_type_result;
break;
}
int read_name_result = read_line(file_buffer, BUFF_SIZE, dest->name, NAME_TYPE_SIZE, stream);
if (read_name_result != 0)
{
error = read_name_result;
break;
}
char value_buffer[VALUE_SIZE] = { 0 };
int read_value_result = read_line(file_buffer, BUFF_SIZE, value_buffer, VALUE_SIZE, stream);
if (read_value_result != 0)
{
error = read_value_result;
break;
}
if (0 == strcmp(find_name, dest->name))
{
if (1 != sscanf(value_buffer, "%d", &dest->value))
{
error = CANT_FORMAT_VALUE;
}
break;
}
}
fclose(stream);
return error;
}
You just need to call the function find_var_in_file like in main. I loop over all the lines of the file and search for the var name. If have formating error or not find the name of the var in the file return the error code.
If the file you are trying to read is a text file (which it is in your case), then use fgets() to read its content. Also, if its content has a consistent format, then consider using sscanf() to do your parsing.
I don't understand why you are using a pointer to struct variable to save data. You can simply use a struct variable object and access its fields with .
Your code should look something like that:
#include <stdio.h>
#include <stdlib.h> // For exit()
#include <string.h> // for strlen()
struct variable {
char type[10];
char name[10];
int value;
};
int main()
{
FILE *file = fopen("input.txt", "r");
if (!file) {
fprintf(stderr, "Could not read file\n");
return 1;
}
struct variable object2;
char buffer[1024];
while (fgets(buffer, 1024, file)) {
if (sscanf(buffer, "%9s %9s %d", object2.type, object2.name, &object2.value) != 3) {
fprintf(stderr, "Error parsing file\n");
fclose(file);
return 1;
}
printf("%s %s %d\n", object2.type, object2.name, object2.value);
}
fclose(file);
}
Now, if you want to store all the lines of your file into variables to use them later, then first you need to count the number of lines in your file (let's call it n) and second, allocate a dynamic array of size n.
fscanf(file,"%s\n%s\n%d\n",object2->type,object2->name,&object2->value);

Segmentation fault reading random lines of text?

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.
}```

Warning When Returning Pointer

My file include 1 word in every line(i know the number of the line).I want to read random line, store it's adress in pointer and return to main function. There is 1 warning (19|warning: return makes pointer from integer without a cast [-Wint-conversion]|) and when i run the program it dont prints anything.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
char *word(char *file, char *str);
int main() {
char *str;
printf("%s",word("words.txt",str));
}
char *word(char *file, char *str) {
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;
for (end = loop = 0; loop < line; ++loop) {
if (0 == fgets(str, sizeof(str), fd)) {
end = 1;
break;
}
}
if (!end)
return (char*)str;
fclose(fd);
}

Reading a file, modifiying each line, storing it into a buffer, printing all at once

This is the file:
line 1
line 2
line 3
How to read the file line by line...
Append a suffix to each line..
FILE *fp = fopen ("file", "r");
while (fgets (buffer, sizeof (buffer), fp) != NULL) {
// append "test" to each line.
// store the result in a buffer named "result"
}
fclose (fp);
print the result all at once:
printf( "%s", result );
Expected result :
line 1test
line 2test
line 3test
The below program might do the requirement but it is not efficient enough. I am just giving a rough example. Hope this helps.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void display(char** temp,int LinesWritten);
int main()
{
FILE *fp;
char *buffer = (char*)malloc(sizeof(char)*101); // 101 is just an assumption. dynamic size may be decided
char **result = (char**)malloc(sizeof(char*)*10); // 10 is just an assumption. dynamic size may be decided
int LinesWritten = 0;
char **temp = result;
char **freetemp = result;
if((fp = fopen("file.txt","r"))==NULL)
{
printf("Error while opening file\n");
exit(1);
}
while((fgets(buffer,100,fp))&&(!(feof(fp)))) //assuming that 100 characters will be read into the buffer
{
if(*result = (char*)malloc(sizeof(char)*10))
{
sprintf(*result,"%s%s",buffer,"test");
*result++;
LinesWritten++;
}
}
fclose(fp);
display(temp,LinesWritten);
if(freetemp!=NULL)
{
free(freetemp);
}
return 0;
}
void display(char** temp,int LinesWritten)
{
for(int i=0;i<LinesWritten;i++)
{
printf("%s\n",*temp);
*temp++;
}
return;
}

Resources