how can i read a .txt file separated by commas in C? - c

I'm having a lot of problems doing this task. I have a txt with only one line of words separated by commas. I have to read this and put it in an array.
So far i tried using strtok() but it just gives me errors. Here's my code:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<omp.h>
int main(){
char string[5000],list[200],*token,s=", ";
int i;
FILE *lista;
lista=fopen("lista.txt","r");
i=0;
token=strtok(string,s);
strcpy(list[i],token);
while(fscanf(lista,"%s",string)!=EOF){
token=strtok(NULL,s);
strcpy(list[i],token);
i=i+1;
}
fclose(lista);
}
It gives me the" expectig char *restrict" error
I'm seriously out of ideas.
BTW: I'm in Linux

There are many strange things in your code, but i guess, you want something like this:
char string[5000], *list[200], *token;
char * s = ",";
int i;
FILE *lista;
lista = fopen("C:\\File.txt", "r");
int MAX_FILE_SIZE = 1000;
char * buffer = (char*)malloc(sizeof(char)*MAX_FILE_SIZE);
fread(buffer, sizeof(char), MAX_FILE_SIZE, lista);
list[0] = strtok(buffer, s);
for (int i = 1;; i++)
{
list[i] = strtok(NULL, s);
if (list[i] == NULL)
{
break;
}
}
fclose(lista);
What is strange/wrong in your code:
You are passing char* string into strtok function, but this variable is uninitialised when passing
You have file pointer lista, but you never read from this file
You have variable list which is array of 200 chars, but i guess you want to have variable list as a list of strings
strtok eats two parameters, const char* inputString and const char* delimiter. So your variable s should be const char *

Related

Program Hangs when printing contents of array in loop

Hi, i am using the MinGW C Compiler with Code::Blocks and my code hangs when trying to print the contents of an array (well it is a custom data type).
For a quick summary: the program is taking the contents of a txt file and splits
the string up into individual words using a custom data type called a stringArray (the name explains itself). It then should print each word of the file to the user.
The problem is, it hangs and gives me the usual "[PROGRAM NAME HERE] is not responding." After pressing cancel it gives me this result:
Process returned -1073741819 (0xC0000005) execution time : 3.861 s
Press any key to continue.
I am a sort of beginner.
Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
typedef struct stringArray
{
char *string;
}stringArray;
const char delim[2] = " ";
int string_to_array(char *filecontents)
{
char *token;
token = strtok(filecontents, delim);
int i;
int dirtyContentsLength;
stringArray newContents[100];
for(i = 0; i < 100; i++)
{
newContents[i].string = "";
}
i = 0;
while (token != NULL)
{
newContents[i].string = token;
i++;
token = strtok(NULL, delim);
}
return newContents;
}
int open_file(char filename[30])
{
char *file_contents;
long input_file_size;
FILE *input_file = fopen(filename, "rb");
fseek(input_file, 0, SEEK_END);
input_file_size = ftell(input_file);
rewind(input_file);
file_contents = malloc(input_file_size * (sizeof(char)));
fread(file_contents, sizeof(char), input_file_size, input_file);
fclose(input_file);
return file_contents;
}
int lex(char filecontents[30])
{
char *tok = "";
int state = 0;
char *string = "";
}
int main(int argc, char *argv[] )
{
const char *cleanContents;
char *messyContents;
char input[30];
printf("What is the filename? ");
scanf("%s", input);
messyContents = open_file(input);
cleanContents = string_to_array(messyContents);
int contentsLength = sizeof(cleanContents) / sizeof(cleanContents[0]);
int i;
for(i = 0; i < contentsLength; i++)
{
printf("%s\n", cleanContents[i]);
}
printf("Done");
return 0;
}
You have multiple problems with your code:
string_to_array() is declared to return an int, but in reality it is returning a stringArray
Same with open_file() function, Declared to return an int, but actually returning a char*
string_to_array is returning an element that was declared locally. This means that once the function is returned, that memory is no longer valid, but it has passed it on to the caller.
Your structure name is misleading. A char* is a character array (a string). Thus the name charArray would be more appropriate. For the structure to be a string array it has to be a char**, ie an array of character arrays (array of strings)
Int the printf() in the main() function you are not passing the string (thus a compilation warning is generated)
You are not initializing memory to all 0. This is ideal as otherwise the memory will contain random data which will be interpreted as a string untill the first null terminator (\0 encountered)
The following code is a modified working version of what you are trying to achieve with comments about each change:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
typedef struct stringArray
{
char *string;
}stringArray;
const char delim[2] = " ";
// Now string_to_array takes the memory location to write output to as a first parameter so that the
// memory will reside in the callers scope (refer to problem 3 above)
// Additionally return type was now set to void (refer to problem 1)
void string_to_array(stringArray newContents[100], char *filecontents)
{
char *token;
token = strtok(filecontents, delim);
int i;
int dirtyContentsLength;
for(i = 0; i < 100; i++)
{
newContents[i].string = "";
}
i = 0;
while (token != NULL)
{
newContents[i].string = token;
i++;
token = strtok(NULL, delim);
}
// return now was removed. result written directly in memory passed as parameter by the caller.
}
// open_file changed to return a char* (refer to problem 2)
char* open_file(char filename[30])
{
char *file_contents;
long input_file_size;
FILE *input_file = fopen(filename, "rb");
fseek(input_file, 0, SEEK_END);
input_file_size = ftell(input_file);
rewind(input_file);
file_contents = malloc(input_file_size * (sizeof(char)));
fread(file_contents, sizeof(char), input_file_size, input_file);
fclose(input_file);
return file_contents;
}
int lex(char filecontents[30])
{
char *tok = "";
int state = 0;
char *string = "";
}
int main(int argc, char *argv[] )
{
stringArray cleanContents[100];
// Initializing memory to all 0s (refer to problem 6)
memset(cleanContents, 0 ,sizeof(cleanContents));
char *messyContents;
char input[30];
printf("What is the filename? ");
scanf("%s", input);
messyContents = open_file(input);
string_to_array(cleanContents, messyContents);
int contentsLength = sizeof(cleanContents) / sizeof(cleanContents[0]);
int i;
for(i = 0; i < contentsLength; i++)
{
// Checking that at least one character is present in the string before printing it...
if (cleanContents[i].string[0])
{
// Printing the string within the 'stringArray'. (refer to problem 5)
printf("%s\n", cleanContents[i].string);
}
}
printf("Done\n");
return 0;
}

Splitting a string in a file into array in c

I'm new to programming,and I have a small problem.
I have a file named questions.txt containing a string of questions, I want to read the string from the file then split it into array with each question having an index, for example a[i] = "Question i" etc.
I did so many tries, but it always ends up reading the last line in the file, when write a loop the program stops working.
This is what i came up with, it's all probably wrong:
char str[200];
char *ptr;
FILE * fp = fopen("questions.txt", "r");
while(fgets(str, 200, fp)!= NULL)
printf("%s", str);
ptr = strtok(str, "\n");
while(ptr != NULL)
{
ptr = strtok(str, "\n");
printf("%s\n", ptr);
ptr = strtok(NULL, "\n");
}
fclose(fp);
The file is:
what is your course?
who is your instructor?
Output i get is:
what is your course?
who is your instructor?
who is your instructor?
I want to read the string from the file then split it into an array with each question having an index...
Let me say, that you don't have a string to split into array.
You should better have a file with a one string of questions like this:
what is your course?:who is your instructor? // `:` is some kind of delimiter
I can suppose that you want to make a vector (one dimensional array) of the file. And in that vector, each element will contain a question from the file. Right?
I can share with you a function from my library I've made at the university. I'll write here a simple program. But it uses delimiters - :, for example. You can modify this function for working without delimiters -- this only depends on you.
In two words, this little program does the following:
// BEFORE: you have a string that ends with a null terminating character.
Question_1_abcbadsad:QUestion_2asasdasd:Question_3sldasdsa\n
^
here ^<< printing 'string' stops
// AFTER: an array of questions. Each of them ends with a null terminating character.
Question_1_abcbadsad\nQUestion_2asasdasd\nQuestion_3sldasdsa\n
^
^<< printing argz[0] will stop here
main.c
#include "argz.h"
int main()
{
error_t func;
char *argz; // pointer to a vector; to an array of questions
size_t argz_len;
// size of that vector (the size of the string you've got from the file)
// Consider `string` to be your `ptr`. You read a string from the file so
// `ptr` will point to the string.
char *string = "Question_1_abcbadsad:QUestion_2asasdasd:Question_3sldasdsa";
// Here `:` is a separate character.
func = argz_create_sep(string, ':', &argz, &argz_len);
if(func == OK)
argz_print(argz, argz_len);
else
printf("ERROR\n");
return 0;
}
argz.c
#include "argz.h"
error_t argz_create_sep (const char *string, int sep, char **argz, size_t *argz_len)
{
int i;
char *ch;
int len = strlen(string);
if(len==0)
return ENOMEM;
*argz = (char*) malloc (sizeof(char)*(len + 1));
strcpy(*argz, string);
*argz_len = strlen(*argz);
ch = *argz;
for(i = 0; i < len; i++) {
if(*ch == sep) *ch='\0';
ch++;
}
return OK;
}
void argz_print(const char *argz, size_t argz_len)
{
const char *ch;
int i;
ch = argz;
for(i = 0; i < argz_len; i++) {
if(*ch == '\0')
printf("\n");
else
printf("%c",*ch);
ch++;
}
printf("\n\n\n");
}
argz.h
#include <stddef.h> // for size_t
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef enum {OK, ENOMEM} error_t;
/* function prototypes */
error_t argz_create_sep (const char *string, int sep, char **argz, size_t *argz_len);
void argz_print (const char *argz, size_t argz_len);
I think what you want is something like this:
#include <stdio.h>
int main(){
int i=0;
char str[200],s='1'; //s is give a random character
FILE * fp = fopen("questions.txt", "r");
while (s!=EOF){ //works until s= the end of file
s=getc(fp); //s starts to receive characters from text file
str[i]=s; //each character of text is placed into the string array
i++;
}
str[i]='\0'; //s reached EOF so lets indicate where we stopped in the string
fclose(fp);
printf("%s\n",str);
//EDIT: changing 1D str to 2D str2
char str2[10][200]; // 10 for max no. of questions, 200 - length of each question
int j=0,k=0;
i=0;
for(j=0;j<200;j++){
str2[i][k]=str[j];
k++;
if (str[j]=='\n'){
i++;
k=0;}
}
for(i=0;i<10;i++) //prints your 2D string array
printf("%s",str2[i]); //after the last question there will be junk
return 0;
}

C - Using strtok gives me only the first word of each line?

My code is as follows. I am using a struct and taking in an input text file. I separate it into lines, then attempt to separate each line into its individual words. Using strtok, it is currently only printing the first word of each line. How can I fix this?
typedef struct {
char linewords[101];
char separateword[101];
} line;
The following is in main:
line linenum[101];
char var[101]
char *strtok(char *str, const char delim);
while fgets(linenum[i].linewords, 101, stdin) != NULL) {
char* strcopy();
char* strtok();
strcpy(linenum[i].separateword,linenum[i].linewords);
strtok(linenum[i].separateword, " "); /*line i'm referring to*/
i++;
}
}
I apologise in advance for any confusion. What I want is to have it so linenum[i].separateword[0] will return the first word, etc. Is this possible? Or is there another way of splitting my input into words?
Thank you
#include <stdio.h>
#include <string.h>
typedef struct {
char linewords[101];
char *separateword[51];
} line;
int main(void){
line linenum[101];
int i = 0;
while(fgets(linenum[i].linewords, sizeof(linenum[i].linewords), stdin) != NULL) {
char *token, *delm = " \t\n";
int j = 0;
for(token = strtok(linenum[i].linewords, delm);
token;
token = strtok(NULL, delm)){
linenum[i].separateword[j++] = token;
}
linenum[i++].separateword[j] = NULL;
}
{//test print
char **p = linenum[0].separateword;
while(*p)
puts(*p++);
}
return 0;
}

C - Storing Values from text into Arrays

I'm trying to store different values that are taken from a file line by line. The lines in the text file read as something shown below
100000,player1,long title name
300000,someotherplayer,another long title name
45512845,thisplayer,one more long title name
I want to store each value that is comma separated into three different arrays, (int)number, (str)player_name, (str)title_name.
I have some code below, but it doesn't compile.
ptr_file=fopen("text.txt", "r");
char buffer[1000];
int line;
line = 0;
while(fgets(buffer, sizeof(buffer), ptr_file) != NULL){
char number[line]=strtok(buffer, ",");
char player_name[line]=strtok(NULL, ",");
char title_name[line]=strtrok(NULL, ",");
}
Can someone give me some advice on this?
So, there are a couple of issues with your code,
You open the file in mode "o" which I'm not really sure what it is, I suspect you want "r"
strtok returns a char * which you cannot assign to a char[].
One the second run through the loop you will overwrite the data in buffer.
I would do something like this:
struct player {
int number;
char player_name[64];
char title_name[256];
};
int main(void) {
FILE *ptrfile=fopen("text.txt", "r");
char buffer[1000];
int line;
struct player players[16];
line = 0;
if(ptrfile==NULL) return 0;
while(fgets(buffer, sizeof(buffer), ptrfile) != NULL){
if(strcmp(buffer, "") == 0) return 0;
char *number=strtok(buffer, ",");
char *player_name=strtok(NULL, ",");
char *title_name=strtok(NULL, ",");
players[line].number=atoi(number);
strcpy(players[line].player_name, player_name);
strcpy(players[line].title_name, title_name);;
line++;
}
fclose(ptrfile);
return 0
}
function strtok return a pointer, so it should be
char* p = strtok(...)
Check the reference here
This is something I did that was similar to what you seem to be doing. The problem you will find is that you want to make each value into a char* but you have to malloc each one then you can connect this char* into the array. It would also just be easier to do that with the numbers to then turn them into int later on.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
char *msg[100];
char temp[100];
int length, i;
int num = 0;
while((scanf("%s", &temp[0]) != EOF))
{
length = strlen(temp);
msg[num] = malloc((length+1 )* sizeof(char));
strcpy(msg[num], temp);
num++;
}
printf("There are %d words in the this input.\n", num);
for(i = 0; i < num; i++)
{
printf("%s\n", msg[i]);
}
return 0;
}
The thing with the malloc is that you will have to have each one unique because the words are all different sizes. I know this example isn't exactly what your doing but it will get you in the right direction.

CSV into array in C

I'm trying to load a CSV file into a single dimentional array. I can output the contents of the CSV file, but in trying to copy it into an array I'm having a bit of trouble.
Here is my existing code, which I realise is probably pretty bad but I'm teaching myself:
#include <stdio.h>
#include <string.h>
#define MAX_LINE_LENGTH 1024
#define MAX_CSV_ELEMENTS 1000000
int main(int argc, char *argv[])
{
char line[MAX_LINE_LENGTH] = {0};
int varCount = 0;
char CSVArray[MAX_CSV_ELEMENTS] = {0};
FILE *csvFile = fopen("data.csv", "r");
if (csvFile)
{
char *token = 0;
while (fgets(line, MAX_LINE_LENGTH, csvFile))
{
token = strtok(&line[0], ",");
while (token)
{
varCount++;
CSVArray[varCount] = *token; //This is where it all goes wrong
token = strtok(NULL, ",");
}
}
fclose(csvFile);
}
return 0;
}
Is there a better way I should be doing this? Thanks in advance!
*token means dereferencing the pointer token which is the address of the first character in a string that strtok found. That's why your code fills CSVArray with just the first characters of each token.
You should rather have an array of char pointers to point at the tokens, like:
char *CSVArray[MAX_CSV_ELEMENTS] = {NULL};
And then assign a pointer to its elements:
CSVArray[varCount] = token;
Alternatively, you can copy the whole token each time:
CVSArray[varCount] = malloc(strlen(token)+1);
strcpy(CVSArray[varCount], token);
You are right about the problem line. It is because you are assigning a pointer, not copying the text.
Try here http://boredzo.org/pointers/ for a tutorial on pointers.
It looks like you're trying to put the char * that comes back from strtok into the char array.
I think you want to declare CSVArray as:
char * CSVArray[MAX_CSV_ELEMENTS] = {0};

Resources