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);
Related
I'm reading file using fread().[read file only]
On compilation, the compiler throws a "Segmentation fault (core dumped)" error.
I'm using structure.
I wrote this code.
type #include <string.h>
#include <stdio.h>
#include <stdlib.h>
int twilio_send_functionapi(char *channel, char *status); // function declartion
struct credentials
{
char *account_sid;
char *auth_token;
char *from_number;
char *to_number;
} c1;
int main(int argc, char *argv[])
{
FILE *fp;
struct credentials input;
fp = fopen("data.config", "r");
if (fp == NULL)
{
printf("Error\n");
return -1;
}
dentials.to_number = (char*)malloc(sizeof(char)*100);
while(fread(&c1,sizeof(struct credentials),1 ,fp))
fscanf(fp,"%s %s %s %s", c1.account_sid, c1.auth_token,c1.from_number, c1.to_number);
char *channel,*status;
channel = argv[1];
status = argv[2];
twilio_send_functionapi(channel,status); //function call
}
Don't know where I'm mistaken.
here is .conf file which needs to be read
account_sid : AC40cfb4f3e98b55b13a9b93527683171e
auth_token : 5f6906d7847ad1fc1fc1170ab60e40fd
from_number : 15867854760
to_number : 1212321123
Instead of fread(), fscanf(), use fgets() to read a line of the file into a string.
// 123456789 123456789 123456789 123456789
//account_sid : AC40cfb4f3e98b55b13a9b93527683171e
#define SID_LEN 34
struct credentials {
char account_sid[SID_LEN + 1]; // Use array here, not pointer.
// ... omitted for brevity
} c1;
#define LINE_SIZE 100
char line[LINE_SIZE];
if (fgets(line, sizeof line, fp)) {
if (sscanf(line, "account_sid : %34s", c1.account_sid) == 1) {
; // Success
} else {
; // Failed
}
Continue likewise for the other c1 members`.
Thank you everyone.
I resolve my problem.
char credential[4][100] ;
int main()
{
FILE *fp;
fp = fopen("data.config", "r");
if (fp == NULL)
{
printf("Error\n");
return -1;
}
printf("File is opened\n");
if ((fscanf(fp,"account_sid-%s\n",credential[0])!= 1))
{
printf("error reading account_sid value\n");
return -1;
}
fclose(fp);
}
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 */
Sample Text file:
234765 PETER
867574 SMITH
I'm trying to take the id and string from the text file and save it into a struct. The id is saving fine but the string isn't.
typedef struct student
{
int id[DATA_SIZE];
char *student[DATA_SIZE];
}studentinfo;
studentinfo list;
struct student *create_space(int size)
{
struct student *tmp = (struct student*)malloc(size*sizeof(struct student));
return(tmp);
}
struct student * readData(struct student*pointer,studentinfo v)
{
int count =0;
int tmpid;
char str[256];
FILE* in_file;
in_file = fopen("studentlist.txt","r");
while(fscanf(in_file,"%d",&tmpid)!= EOF && count<DATA_SIZE)
{
fscanf(in_file,"%s",v.student[count]);
//printf("%s\n",str );
v.id[count]=tmpid;
count++;
}
pointer =&v;
return pointer;
}
int main()
{
struct student *data;
struct student *sdata;
data = create_space(1);
sdata = readData(data,list);
//printf("%s\n",sdata->student[2] );
}
Their are a couple of issues:
fscanf() reads formatted input, and returns the number of items read.
This line:
while(fscanf(in_file,"%d",&tmpid)!= EOF && count<DATA_SIZE)
Could be this:
while (count < DATA_SIZE && fscanf(in_file, "%d %255s", &list.id[count], str) == 2) {
Which verifies that 2 values are being read on each line successfully.
You are not checking if in_file returns NULL. It's safe to do this. This goes the same for malloc().
You need to correctly create space for char *students[DATA_SIZE], as this is an array of char * pointers. Once you allocate space for this via malloc() or strdup(), then you can copy the contents into students.
Here is an example of doing such a thing:
while (count < DATA_SIZE && fscanf(in_file, "%d %255s", &list.id[count], str) == 2) {
/* allocate space for one student */
list.student[count] = malloc(strlen(str)+1);
if (!list.student[count]) {
printf("Cannot allocate string\n");
exit(EXIT_FAILURE);
}
/* copy it into array */
strcpy(list.student[count], str);
count++;
}
Here is an example that you can use to help achieve your desired result:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define DATA_SIZE 256
typedef struct {
int id[DATA_SIZE];
char *student[DATA_SIZE];
} studentinfo_t;
int main(void) {
FILE *in_file;
studentinfo_t list;
char str[DATA_SIZE];
size_t count = 0;
in_file = fopen("studentlist.txt", "r");
if (!in_file) {
fprintf(stderr, "%s\n", "Error reading file");
exit(EXIT_FAILURE);
}
while (count < DATA_SIZE && fscanf(in_file, "%d %255s", &list.id[count], str) == 2) {
list.student[count] = malloc(strlen(str)+1);
if (!list.student[count]) {
printf("Cannot allocate string\n");
exit(EXIT_FAILURE);
}
strcpy(list.student[count], str);
count++;
}
for (size_t i = 0; i < count; i++) {
printf("%d %s\n", list.id[i], list.student[i]);
}
return 0;
}
I am trying to read a file test.txt via fscanf and store it in a array of struct. This is what I tried. Problem here is that fscanf is not working as it is supposed to. After reading the file, I am also trying to print it on screen, but it won't work.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Item {
double value;
int unit;
char name[50];
};
int load(struct Item* item, FILE* data);
void display(struct Item item, int variableA);
int main()
{
struct Item I;
int i;
char ck;
ck = fopen("test.txt", "r");
if (ck)
{
for (i = 0; i < 3; i++)
{
load(&I, ck);
display(I, 0); //DISPLAY FUNCTION THAT READS test.txt and DISPLAYS
}
fclose(ck);
}
return 0;
}
int load(struct Item* item, FILE* data)
{
fscanf(data, "%d,%.2lf,%s\n", &(*item).unit,&(*item).value,&(*item).name);
return 0;
}
void display(struct Item item, int variableA)
{
printf("|%3d |%12.2lf| %20s |***\n", item.unit, item.value, item.name);
return;
}
This is what I have in test.txt file:
205,11.20,John Snow
336,23.40,Winter is coming
220,34.20,You know nothing
Error: Program compiles with some warnings , but I get segmentation fault when I execute the code.
Any idea why?
Output Expectation: OUTPUT should be read from test.txt file and should be displayed on to the screen.
Multiple problems in the program:
1.
char ck;
ck = fopen("test.txt", "r");
fopen returns a FILE*, not a char, use
FILE* ck = fopen(...);
2.
fscanf(data, "%d,%.2lf,%s\n", &(*item).unit,&(*item).value,&(*item).name);
always check return value of fscanf, if it is smaller than the number of fields you requested, the following call to fscanf is unlikely to do what you expect. Also, *item.unit is the same as item->unit, use item->unit because it is shorter and cleaner:
int ret = fscanf(data, "%d,%lf,", &item->unit, &item->value);
if (ret != 3) { // error }
Third, %s matches a sequence of non-white-space characters, so when fscanf reads "John", it will stop, and the next fscanf call will get to read "Snow" while expecting an integer.
So to input a string with whitespace, use fgets instead, and remember to remove the newline character in the end.
Try following:
int main(void)
{
struct Item I;
int i;
FILE* ck;
int ret;
ck = fopen("test.txt", "r");
if (ck)
{
for (i = 0; i < 3; i++)
{
ret = load(&I, ck);
if (ret < 0)
break;
display(I, 0); //DISPLAY FUNCTION THAT READS test.txt and DISPLAYS
}
fclose(ck);
}
return 0;
}
int load(struct Item* item, FILE* data)
{
int ret = fscanf(data, "%d,%lf,", &item->unit, &item->value);
if (ret != 2) {
return -1;
}
fgets(item->name, sizeof item->name, data);
item->name[strlen(item->name)-1] = '\0';
return 0;
}
void display(struct Item item, int variableA)
{
printf("|%3d |%12.2lf| %20s |***\n", item.unit, item.value, item.name);
return;
}
It outputs:
$ ./a.out
|205 | 11.20| John Snow |***
|336 | 23.40| Winter is coming |***
|220 | 34.20| You know nothing |***
You can try this different approach.
It uses:
malloc,realloc to allocate and reallocate memory for array of structs. I assumed that much larger text files with more lines will be used and this allows the array to resize when needed to accommodate more information.
strtok to parse each peice of data between , delimeters, and then store them into the array of structures.
Checks return value of pointers to avoid segmentation faults.
Uses fgets to read each line of the file into a string, from which we can parse ourselves afterwards.
This is the proposed code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NAMESTRLEN 50
#define INITSIZE 3
#define MAXSIZE 100
typedef struct {
int unit;
double value;
char name[NAMESTRLEN+1];
} item_t;
typedef struct {
item_t *items;
int numlines;
} allitems_t;
allitems_t *initialize_arraystructs(void);
void print_arraystructs(allitems_t *allitems);
void read_insert_items(FILE *filestream, allitems_t *allitems);
void check_ptr(void *ptr, const char *msg);
int
main(void) {
allitems_t *allitems;
FILE *fp;
fp = fopen("test.txt", "r");
if (fp == NULL) {
fprintf(stderr, "%s\n", "Error reading file!\n");
exit(EXIT_FAILURE);
}
allitems = initialize_arraystructs();
read_insert_items(fp, allitems);
print_arraystructs(allitems);
return 0;
}
void
read_insert_items(FILE *filestream, allitems_t *allitems) {
int count = 0;
char line[MAXSIZE];
char *unit, *value, *name;
size_t numitems = INITSIZE;
allitems->items = malloc(numitems * sizeof(item_t));
check_ptr(allitems->items, "Initial Allocation");
while (fgets(line, MAXSIZE, filestream) != NULL) {
unit = strtok(line, ",");
value = strtok(NULL, ",");
name = strtok(NULL, "\n");
if (count == numitems) {
numitems *= 2;
allitems->items = realloc(allitems->items, numitems * sizeof(item_t));
check_ptr(allitems->items, "Reallocation");
}
allitems->items[count].unit = atoi(unit);
allitems->items[count].value = atof(value);
strcpy(allitems->items[count].name, name);
count++;
allitems->numlines++;
}
}
allitems_t
*initialize_arraystructs(void) {
allitems_t *allitems;
allitems = malloc(sizeof(allitems_t));
check_ptr(allitems, "Initial Allocation");
allitems->items = NULL;
allitems->numlines = 0;
return allitems;
}
void
print_arraystructs(allitems_t *allitems) {
int i;
for (i = 0; i < allitems->numlines; i++) {
printf("%d,%.2f,%s\n",
allitems->items[i].unit,
allitems->items[i].value,
allitems->items[i].name);
}
}
void
check_ptr(void *ptr, const char *msg) {
if (!ptr) {
printf("Unexpected null pointer: %s\n", msg);
exit(EXIT_FAILURE);
}
}
I have text file emails.txt..this is how the entry in the text file..
Emails.txt
abc#gmail.com
sfs#yahoo.com
i have to obtain the data from file and select 2 entries from the data randomly..
could anyone suggest me the technique to do this.
Thanks
You can read the file twice, first time to count the number of lines, then generate two random numbers in the range of 0 to number_of_lines found and then read the file again while looking for the lines you are interested in or you can do it like this:
Filename: emails.c
#include
int main (int argc, char **argv)
{
// open a handler to your file (read)
FILE *fp = fopen("emails.txt", "r");
// check if we have successfully opened the file for reading
if (fp != NULL)
{
// in your case 256 characters is enough for line size
// since emails are not that long but if longer buffer overflow
// is very possible and its not helpful as stackoverflow.com is :p
char line_buffer[256];
// count the number of lines read
unsigned int lines_read = 0;
// read up to line size or until EOL (End of Line) or EOF (End of File)
// will return NULL on error or eof
while (fgets(line_buffer, sizeof(line_buffer), fp) != NULL) {
// use rand() and seed it with the number of lines read
if ((rand() % ++lines_read) == 0) {
// do something with this line, it was randomly picked
// for the example, will print it on the screen
printf("%s \n", line_buffer);
}
}
// close file handler as we don't need it anymore
fclose(fp);
}
// return to the OS
return 0;
}
NOTE: This is C implementation, so save as .c file.
If you are using c++, and not just c -- you can use something like the following code:
#include <iostream>
#include <fstream>
#include <time.h>
#include <vector>
using namespace std;
int getrand(int num, int notnum)
{
int result = 0;
while (true)
{
result = abs(rand()) % num + 1;
if (result != notnum)
{
return result;
}
}
}
int main()
{
ifstream emails;
srand(time(NULL));
emails.open("emails.txt");
string email;
vector<string> emailVector;
while (emails >> email)
{
emailVector.push_back(email);
}
int index1 = getrand(emailVector.size(), 0);
int index2 = getrand(emailVector.size(), index1);
cout << "email 1: " << emailVector[index1 - 1] << endl;
cout << "email 2: " << emailVector[index2 - 1] << endl;
}
This will work:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define BUF_SIZE 4096
#define RAND_COUNT 2
int count_lines(FILE *fp) {
char buf[BUF_SIZE];
int line_count=0;
fseek(fp, 0L, SEEK_SET);
while(fgets(buf, BUF_SIZE, fp) != NULL) {
line_count++;
}
fseek(fp, 0L, SEEK_SET);
return line_count;
}
int line_num(FILE *fp, char *buf, int line_num){
fseek(fp, 0L, SEEK_SET);
int i=0;
while(fgets(buf, BUF_SIZE, fp) != NULL) {
if (++i == line_num) {
return i;
}
}
return -1;
}
int main (int argc, const char * argv[]) {
FILE *fp=NULL;
char buf[BUF_SIZE];
char name[]="email.txt";
if((fp=fopen(name, "r"))==NULL){
printf("can't open: %s\n\n",name);
return -1;
}
int line_count=count_lines(fp);
printf("line count=%i\n",line_count);
srand ((unsigned int)time(NULL));
for (int i=1; i<=line_count; i++) {
line_num(fp,buf,i);
printf("%i = %s",i,buf);
}
for (int i=0; i<RAND_COUNT; i++) {
int a=(rand() % line_count);
line_num(fp,buf,a);
printf("line %i = %s\n",a,buf);
}
fclose(fp);
return 0;
}