Create Array from File Import in C - c

I am trying to write a program that reads a file formated as below:
city city weight
It will be used to create a graph. What I have below isn't working and I don't understand why. I am admittedly pretty shakey when it comes to working with char arrays and arrays of strings.
int main() {
// Create an empty graph
graph_t* graph = create_graph();
// string buffer and tokens
char buffer[25];
char* source;
char* dest;
char* weight;
int key, a, b, c, d, e, f;
char cities[25][25];
//Open file and Read data from datafile city.dat
FILE *fp;
fp = fopen("city.dat","r");
if(fp==NULL){
printf("no such file exists\n");
return 0;
}
b = 0;
while(fgets(buffer, 25, fp)!=NULL){
printf("inside while loop\n");
printf("before tokenization\n");
source = strtok(buffer, " ");
printf("after tokenization\n");
char tempSource[40];
strcpy(tempSource,source);
printf("tempSource = %s\n", tempSource);
int size = sizeof(cities)/sizeof(cities[0]);
printf("size = %d\n", size);
for(e=0;e<size;e++){
printf("inside first loop\n");
char temp[40];
printf("before strcopy of cities[e]\n");
printf("%s\n", cities[e]);
strcpy(temp,cities[e]);
What I am trying to do is add the strings I'm tokenizing to the cities array only if it doesn't already exist. I've been working on this for days and have made no progress and really don't know what to do next. Any help or clarification would be greatly appreciated.
When I print the value of cities[e] I either get a blank or a memory address.

Related

there is a easy way to visualize and modify a txt file?

i'm having a little big trouble in c. in particular im not able to save and modify a .txt file on an easy and efficient way.
the fact is: from a file.txt, i have to save all the words on a struct, and after that i will have to do some operations on this, like modify a specific word, a bubble sort, ecc ecc.
Im having problem on how to correctly save all the words in the struct, in the most generic possible way, even if a word from a line of the file is missing.
i mean:
1 line: word1 word2
2 line: word3
3 line: word4 word5
So even if a word is missing, i need to be able to save all this words, leaving something like a missing space in the struct.
the code that im posting is, at the moment, the best i can make with my hands, because i dont have any more ideas about what i should do.
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define MAX (10) //<- is 10 because the max numbers of letters in any single word is less than 10
struct word{
char word1[MAX+1]; //<- here im defying a struct with 2 char. this struct will contain the words coming out from the file.
char word2[MAX+1]; //<- max+1 because i have ti give 1 space for the " " or the "/n" case.
};
struct word *file_read(FILE *fp, int *count){
int dim = 2; //<- the int dim is the dimensione
char buf[1024]; //<- a simple buffer
struct word *w;
int conv = 0; //<- another counter that i will use in sscanf
int i;
if(!(w = calloc(dim , sizeof(*w)))){
free(w);
}
while(fgets(buf, sizeof(buf),fp)!= NULL){
conv = sscanf(buf, "%s %s", w->word1, w->word2);
if(conv >= 1){ //if conv doesnt increase, just no print
printf("\n%s ", w[*count].word1);
}
if(conv == 2){ //the same operation
printf("%s", w[*count].word2);
}
i++;
if(*count>= dim){
dim *= 2;
struct word* temp = realloc(w, sizeof(*w)*dim);
if(temp != NULL){
w = temp;
} else{
free(w);
return NULL;
}
(*count)++;
}
}
return w;
}
int main(int argc, char *argv[]){ //<- the file will be passed by argv[1] argument
FILE *fp; //<- im defying the FILE type
fp= fopen(argv[1], "r"); //<- im opening the file passed from argv[1], in reading mode
if(fp == 0){ //<- if file is not loaded, the programm have to stop.
printf("FILE IS NOT LOADED");
return 1;
}
struct word *w; //<- im creating a struct pointer called w
int count= 0;
if(!(w = file_read(fp, &count))){ //<- going to do the reading subroutine
return 0;
}
//AFTER THE READING, I SHOULD BE ABLE TO SAVE ALL THE WORDS IN THE STRUCT
//AND I SHOUL BE ABLE TO DO SOME OPERATIONS, LIKE VISUALIZE IT DIFFERENT WAYS
//DO BUBBLE SORT, QSORT, MODIFY THE WORDS IN THE STRUCT, ECC...
}
so, please, how can i make it works???? thank you everybody.
i hope i've been clear :)
user3386109's suggestion of adding int conv to the word structure is good. Still there are errors:
(*count)++ is out of place, so that it's never reached. Move it to the place of the pointless i++.
In order to not store every line's words in the first structure, change all w-> to w[*count]..

Storing certain information from a file to a data structure

I am currently learning about to how to data structures in C and I need a little help. I am supposed to take information about classes from a .txt file and store the information in a data structure; but I am having trouble doing so. I am also sure that I am also screwing up a lot of other things in my program, so feel free to bash on my program and tell me what I am doing wrong so I can learn from my mistakes.
Here is one line of information that I am trying to store:
M273 Multivariable Calculus :MWF 0900-0950 2
where the first part is the course number, the second part is the course name, the third part is the days and time the course is available and the last number represents what year you should be in to take the course (2 translates to sophomore).
Below is my code:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define EMAX 250
typedef struct class{
char *classNumber[EMAX];
char *className[EMAX];
char *classTime[EMAX];
char *classStanding[EMAX];
}class;
void menu(class*info, char buffer[], FILE*file);
void setInformation(class*info, char buffer[], FILE*file);
int main(void)
{
class info[EMAX];
char buffer[EMAX];
File *file;
setInformation(info, buffer, file);
menu(info, buffer, file);
return(0);
}
void menu(class*info, char buffer[], FILE*file)
{
int user_input=0;
do {
printf("\nSelect one of the following options: \n");
printf("1) Print all information about all classes in order of the class number\n");
printf("5) Quit\n");
scanf("%d", &user_input);
if(user_input==1)
{
//getInformation(info, buffer, file);
}
}while(user_input!=5);
}
void setInformation(class*info, char buffer[], FILE*file)
{
size_t count = 0;
char line[50];
char *token;
file = fopen("classes.txt", "r");
while(fgets(line, sizeof(line), file)!=NULL)
{
token=strtok(line, " "); //Only gets the course number
strncpy(info[count].classNumber, token, strlen(token));
count++;
}
fclose(file);
}
As you can tell, I can only extract the course number with this code. I would prefer to store all the data in one while loop and I have tried to extract more information by adding another token to stop as soon as it reaches the ":" before the day and time but I can't figure out how to get it to work. I also get a lot of warnings when I compile this, so I welcome any advice to help my trash code. I appreciate any help
*scanf() is great:
#include <stdlib.h>
#include <stdio.h>
#define EMAX 250
#define STRING(X) #X
#define STRINGIFY(X) STRING(X)
typedef struct class_tag {
char classNumber[EMAX + 1];
char className[EMAX + 1];
char classTime[EMAX + 1];
char classStanding[EMAX + 1];
char foo[EMAX + 1];
} class;
int main(void)
{
char const *input_filename = "test.txt";
FILE *input = fopen(input_filename, "r");
if (!input) {
fprintf(stderr, "Couldn't open \"%s\" for reading :(\n\n", input_filename);
return EXIT_FAILURE;
}
class c;
class *classes = NULL;
size_t classes_size = 0;
while (fscanf(input, "%"STRINGIFY(EMAX)"s %"STRINGIFY(EMAX)"[^:] %"STRINGIFY(EMAX)"s "
"%"STRINGIFY(EMAX)"s %"STRINGIFY(EMAX)"s",
c.classNumber, c.className, c.classTime, c.classStanding, c.foo) == 5)
{
class *tmp = realloc(classes, ++classes_size * sizeof(*classes));
if (!tmp) {
fputs("Not enough memory :(\n\n", stderr);
fclose(input);
free(classes);
return EXIT_FAILURE;
}
classes = tmp;
classes[classes_size - 1] = c;
}
fclose(input);
for (size_t i = 0; i < classes_size; ++i)
printf("%s %s %s %s\n", classes[i].classNumber, classes[i].className, classes[i].classTime, classes[i].classStanding);
free(classes);
}

Printing line by line using a for loop then scanning to another in c

In the array below i have 11 questions stored. I want each question to be asked one by one and then the answer copied to arrray ans1. Currently the while loop prints the whole file off at the same time. Can someone shed light on how i can use the for loop below the while loop to complete this?
typedef struct{
char q[40][250];
char a[40][250];
} qa;
int main()
{
char *b [40][250];
int w, e, r, t, k, l;
char a1[40][250];
FILE *fp;
fp = fopen("quest.txt", "r");
while (fgets(b, sizeof(b), fp)) {
printf("%s", b);
scanf("%s",a1[1+]);
}
for(l>=0;l<=40;l++){
;}
There are several issues like uninitialized variables (e.g. e, l), reading in into a wrong data structure (fgets(b,... instead of fgets(b[x],...).
See the following code fragment which probably helps you a step further.
Note that I used fgets for reading in the answer; this allows you - in contrast to scanf("%s")- to enter more than one word as an answer (i.e. until you press "enter"):
Hope it helps.
char b [40][250];
char a1[40][250];
FILE *fp;
fp = fopen("quest.txt", "r");
int nrOfQuestions = 0;
while (nrOfQuestions < 40 && fgets(b[nrOfQuestions], sizeof(b[0]), fp)) {
printf("%s", b[nrOfQuestions]);
fgets(a1[nrOfQuestions],sizeof(b[0]), stdin);
nrOfQuestions++;
}
for (int i=0; i<nrOfQuestions; i++) {
printf("q:%s a:%s\n", b[i], a1[i]);
}

Reading from a text file that contains a list

The purpose of the program is to read a text file that contains a list of 55 authors and titles of books. The format of the list goes (author name, booktitle). I can use malloc, strlen, strtok, and strcopy. So far I got the program to read out the names of the authors but I am stuck on how to get the program to read the titles of the books.How would I get the program to read the titles of the books from the text file? I know that there are errors in this code so please be kind .
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void loadBookName(char* filename, char* authorName[55], char* bookName[55]);
int main(int argc, char* argv[])
{
//Create two arrays each with length 55
char* authorName[55];
char* bookName[55];
//Ask the user for the name of the file
char fileName[30];
//Insert your code here
printf("Please enter the name of the file\n");
scanf("%s", fileName);
//Call the method loadBookName
loadBookName(fileName, authorName, bookName);
return 0;
//Print the two arrays to test if the two arrays were correctly loaded with the data
int i = 0;
printf("%-30s%-40s\n", "Author", "Book");
for (i = 0; i < 55; i++) {
printf("%-30s%-40s\n", authorName[i], bookName[i]);
}
}
/*
loadBookName method
This method is responsible for:
1. Take a file containing a book name and the author name as input
2. Open the file
3. Read the information in the file and store it in two arrays: authorName, bookName
4. Return the two arrays to the main method.
*/
void loadBookName(char* filename, char* authorName[55], char* bookName[55])
{
int i;
char string_array[80];
const char comma[2] = ",";
//Open the file
FILE *fp;
fp = fopen(filename, "r");
if (fp == NULL)
{
printf("Failed to open file\n");
exit(1);
}
for (i=0; i<55; i++)
{
fgets(string_array, 80, fp);
authorName[i] = strtok(string_array, comma);
printf("%s\n", *authorName);
}
//Close the file
fclose(fp);
}
when I run the program in terminal it asks me to enter the filename (books.txt). Then when I enter the file name, the program prints a list of 55 authors.
I don't have a compiler in front of me, so excuse the compilation error if it has any. But I think you can try something as below, within your existing code:
UPDATED:
After comments, I've updated one line. This is compiled and working.
Assumptions: User need to take care of error-handling e.g. file not present, file unable to open, buffer overflows etc.
char *token;
for (i=0; i<55; i++)
{
//fgets(string_array, 80, fp);
//This will take care in case if lines are less than 55
if(!fgets(string_array, 80, fp))
break;
//Get the author
token = strtokstring_array, comma);
authorName[i] = token; // or use string copy functions
//Get book name
while( token != NULL )
{
printf( " %s\n", token ); //this shall print author name
token = strtok(NULL, comma);
bookName[i] = token;
printf( " %s\n", token ); //this shall print book name
//EDIT: This is additional line after suggestions
token = strtok(NULL, comma);
}
}
Simple way of separating strings with strlcpy:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
main(void )
{
size_t i = 1;
char *authorName, *bookName;
const char *a_line_in_a_file =
"Lewis Carroll,The Hunting of the Snark";
const char *title = a_line_in_a_file;
while ( *title != ','){
title++;
i++;}
authorName = malloc(i);
bookName = malloc(strlen(title));
title++;
#if __BSD_VISIBLE
strlcpy(bookName, title, strlen(title) + 1);
strlcpy(authorName, a_line_in_a_file, i);
#else
snprintf(bookName, strlen(title) + 1, "%s", title);
snprintf(authorName, i, "%s", a_line_in_a_file);
#endif
printf("%-30s%-40s\n", authorName, bookName);
free(authorName);
free(bookName);
return 0;
}

Reading a csv file using C and then doing string manipulation

First I open a CSV file (Cars.csv) using my C file cars.c. My CSV file would look like:
toyota, 100, 20, 150.50
nissan, 200, 50, 100.75
BMW, 400, 80, 323.00
The 1st column is names, 2nd column is stock, 3rd column is order, 4th column is price.
Then I have to do two works(I will call the program in the commandline with the work name and any other argument I need to pass):
List all the items in the CSV file while the commas cannot be a part of the output. I also have to print headers for each column. (./cars list)
I would send an argument when running the program from the command line. The argument would be one the name of the items in my csv file. Then I would have to subtract 1 from the stock and update the CSVfile. (./cars reduce nissan)
This is how I opened the CSV file.
void main(int argc, char *argv[]) {
FILE *in = fopen ("Cars.csv" ,"rt");
if (in == NULL) {
fclose (in); return 0;
}
//I need to store the data from the CSV file in an array of pointers. I know how to do that, but Im having a problem in storing them without the commas and then doing what I need to do in part 1.
//This is the only code I could write for the 2nd part.
int p =0;
for(p =0; p<; p = p + 4) {
if(strcmp(argsv[2],save[p]) == 0) { //save is the array of pointers where I
int r = int(save[p +1]); //store the data from the csv file
int s = r - 1;
char str[15];
sprintf(str, "%d", s);
save[p +1] = str; // not sure if this line actually makes sense
}
}
There are a couple of possible solutions.
Here's one:
Read the lines into an array of pointers. Allocate array with malloc and reallocate as needed with realloc. Read lines with fgets.
For each line, use strtok to split the line, and do whatever you need with each field.
Another solution:
Use your favorite search engine to search for an existing CSV-reading library (there are many out there, which can handle very advanced CSV files).
Think how the data should be represented and define a structure.
typedef struct {
char *name;
int stock;
int order;
double price;
} car_type;
Open the file: See OP's code
Find how many lines and allocate memory
char buf[100];
size_t n = 0;
while (fgets(buf, sizeof buf, in) != NULL) n++;
rewind(in);
car_type *car = malloc(n * sizeof *car);
if (car == NULL) OutOfMemory();
Read the cars
for (size_t i=0; i<n; i++) {
if (fgets(buf, sizeof buf, in) == NULL) Handle_UnexpectedEOF();
char car_name[100];
if (4 != sscanf(buf, "%s ,%d ,%d, %lf", car_name,
&car[i].stock, &car[i].order, &car[i].price) Handle_FormatError();
car[i].name = strdup(car_name);
}
// Use `car` ...
When done
fclose(in);
for (size_t i=0; i<n; i++) {
free(car[i].name);
}
free(car);

Resources