Adding chars to char array from csv. - c

I am trying to take a csv file and assign the strings from it to a csv. I've tried a couple of things with very little luck. This is what I have so far:
int main(int argc, char* argv []) {
FILE *file = fopen( argv[1], "r" );
int x;
char strings[50];
while ((x = fgetc(file)) != EOF) {
printf( "%c", x);
}
fclose(file);
return 0;
}
I've created the strings char array, but I'm unsure how to assign the contents of my csv into it. Any ideas?
Thanks in advance.

You can use fgets to directly read into array strings-
char strings[255]; //give size accordingly
while(fgets(strings,sizeof strings,file)!=NULL) { //iteratre until fgets return NULL
printf("%s", strings); //print string that is read from file
}
Note-
1.You have not checked value of argc as well as return of fopen . You should probably check them .

You can use your characterwise reading approach. Fill your temporary buffer as you go, but take care not to overflow it. When you encounter a separator – a comma for columns, a newline for rows – process the current buffer.
Reset the buffer, adjust the current row and column and repeat until you find the end of the file. When you want to store the content of a cell, be sure to make a copy, because the scratch buffer will be overwritten.
Here's a simple example that just prints the data:
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
FILE *file = fopen("example.csv", "r");
// check for errors
char buf[50];
int nbuf = 0;
int row = 0;
int col = 0;
for (;;) {
int c = fgetc(file);
if (c == EOF) break;
if (c == '\n' || c == ',') {
buf[nbuf] = '\0';
printf("[%d][%d] '%s'\n", row, col, buf);
nbuf = 0;
if (c == ',') {
col++;
} else {
col = 0;
row++;
}
} else {
if (nbuf + 1 < sizeof(buf)) buf[nbuf++] = c;
}
}
fclose(file);
return 0;
}

Related

Function is not correctly incrementing variable by 1

I have a function that returns the number of lines, characters, and words in an array. For some reason, when i loop through the array to print the values I am only getting the corrrect value for lines, the characters and words are returning as 0. All the functions are predetermined by my professor and my job is to fill them in.
int main(int argc, char **argv)
{
int *myArray = get_counts(argv[1]);
for (int i = 0; i < 3; i++)
{
printf("%d\n", myArray[i]);
}
return 0;
}
int *get_counts(char *filename)
{
FILE *file;
file = fopen(filename, "r");
if (file == NULL)
{
printf("NULL FILE");
}
char c;
int h;
bool whitespace = true;
static int arr[3] = {0,0,0};
do
{
c = fgetc(file);
if (c == '\n')
{
arr[0] ++;
}
}while (c != EOF);
while (true)
{
h = fgetc(file);
if (feof(file))
{
break;
}
else if (ferror(file))
{
printf("error reading file");
}
arr[2] ++;
if (whitespace && !isspace(h))
{
arr[1] ++;
whitespace = false;
}
else if (!whitespace &&isspace(h))
{
whitespace = true;
}
}
fclose(file);
return arr;
}
The best option is probably to just iterate through the file in one loop (you could also rewind() after the first loop). Use the return value of fgetc() to determine of you are at EOF instead of separate feof() calls. I also made the the result array an (out) argument instead of using a static variable (the latter is not reentrant if you ever want to call this from multiple threads and it's easy to do):
#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
void get_counts(char *filename, int arr[3]) {
memset(arr, 0, 3 * sizeof(int));
FILE *file = fopen(filename, "r");
if (file == NULL) {
printf("NULL FILE");
return;
}
bool whitespace = true;
for(;;) {
int c = fgetc(file);
if(c == EOF)
break;
else if(c == '\n')
arr[0]++;
else if (whitespace && !isspace(c)) {
arr[1]++;
whitespace = false;
} else if (!whitespace && isspace(c))
whitespace = true;
arr[2]++;
}
fclose(file);
}
int main(int argc, char **argv) {
int myArray[3];
get_counts(argv[1], myArray);
for (int i = 0; i < 3; i++) {
printf("%d\n", myArray[i]);
}
}
The output on the above file is:
39
94
715
The word count 94 doesn't agree with wc -w but you could be using a different definition of what a word is.
It's a good idea to separate calculations and i/o, so consider opening and closing the file in main() and pass in the file handle. It becomes easy, for instance, to use the stdin file handle instead if you don't want to use a physical file.
After the first do-while loop the condition EOF occurs.
do
{
c = fgetc(file);
if (c == '\n')
{
arr[0] ++;
}
}while (c != EOF);
So the following while loop has no effect.
You should use only one loop to count lines, words and characters.
Pay attention to that the variable c should be declared as having the type int
int c;
Also you need to exit the function if the file was not opened.

How to store text, line by line, to a 2D array in C?

again. I'm new to C. Still thinking in Python terms (readlines, append them to variable) so I'm having difficulties translating that to C. This is what I want to do: open a text file for reading, store each line in an array row by row, print it out to make sure it's stored.
This is how far I've got:
int main(){
FILE * fp = fopen("sometext.txt", "r");
char text[100][100];
if(fp == NULL){
printf("File not found!");
}
else{
char aLine[20];
int row = 0;
while(fgets(aLine, 20, fp) != NULL){
printf("%s", aLine);
//strcpy(text[row], aLine); Trying to append a line (as row)
return 0;
}
Please don't start with "invest in some more time and look somewhere else because it's easy and has been answered". I'm bad at this, and I'm trying.
You can try this. Basically you need an array of arrays to store each line. You find the length of the longest line in the file and you allocate space for it. Then rewind the pointer to the start of the file and use fgets to get each line from the file and strdup to allocate space and copy the line to the respective position. Hope this helps.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
FILE * fp = fopen("sometext.txt", "r");
int maxLineSize = 0, count = 0;
char c;
while ((c = fgetc(fp)) != EOF) {
if (c == '\n' && count > maxLineSize) maxLineSize = count;
if (c == '\n') count = 0;
count++;
}
rewind(fp);
char ** lines = NULL;
char * line = calloc(maxLineSize, sizeof(char));
for (int i = 0 ; fgets(line, maxLineSize + 1, fp) != NULL ; i++) { // +1 for \0
lines = realloc(lines, (i + 1) * sizeof(char *));
line[strcspn(line, "\n")] = 0; // optional if you want to cut \n from the end of the line
lines[i] = strdup(line);
printf("%s\n", lines[i]);
memset(line, maxLineSize, '\0');
}
fclose(fp);
}
You could solve it without copy
The follow code could work:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <math.h>
int main()
{
FILE * fp = fopen("sometext.txt", "r");
if(fp == NULL){
printf("File not found!");
return -1;
}
char text[100][20];
int row = 0;
while(row < 100 && fgets(text[row], sizeof(text[0]), fp) != NULL)
++row;
for (int i= 0; i != row; ++i)
fputs(text[i], stdout);
return 0;
}

Read file with comma separated hex values into array in C

How I can read a text file with comma separated hex values e.g. 0x58,0xA9,0x00 and put its values as elements of an array e.g. LR0
I need to replace this hard-coded with reading from the file:
const unsigned char LR0[] = {0x58,0xA9,0x00}
Here is what I wrote so far. printf("%c", ch); shows me what I need but when I uncomment strcat(LR0, ch); it fails at run time with a segment fault. I don't know if I should use strcat or anything else to append the elements of this LR0 array.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
int ch;
FILE *fp;
//const unsigned char LR0 [1024] = "";
const unsigned char LR0 [] = {};
fp = fopen("test.txt", "r");
if (fp == NULL)
{
perror("Error while opening the file.\n");
exit(EXIT_FAILURE);
}
while((ch = fgetc(fp)) != EOF){
printf("%c", ch);
//strcat(LR0, (char) ch);
}
fclose(fp);
return 0;
}
Sorry so basic question not able to fix it by googling etc. I am not a C developer and I am using gcc on linux. My text file does not contain lines so I cannot use this solution
There are two problems in your code.
LR0 is declared as const with unspecified size which is just pointer, writing to it may result in UB.
strcat needs it arguments as char * type but your second argument is of char type (int ch;).
strcat(LR0, (char) ch)
You can use the fscanf with , as delimiter as below to read only the hex values discarding ,.
int main() {
FILE *fp;
unsigned char LR0 [1024] = {};
fp = fopen("test.txt", "r");
if (fp == NULL) {
perror("Error while opening the file.\n");
exit(EXIT_FAILURE);
}
int i = 0;
while(fscanf(fp, "%c,", &LR0[i]) == 1){
printf("%c", LR0[i++]);
}
fclose(fp);
return 0;
}
const unsigned char LR0 [] = {}; implies a zero length array - that is not standard C yet allowed with some compilers.
strcat(LR0, (char) ch); attempts to 1) write to a const array LR0 and 2) write outside the array - it is only 0 length. Both of the are undefined behavior (UB).
I don't know if I should use strcat
Using str...() functions will not well handle input which may contain many "0x00, 0x00, ...".
How I can read a text file with comma separated hex values e.g. 0x58,0xA9,0x00 and put its values as elements of an array (?)
Read the file to determine its length and contents. I suggest a pass for each.
The below is untested, yet hopefully enough to get OP started. It has little error detection.
// Parse a text file like "0x58,0xA9,0x00"
// Return byte count. Return 0 on error.
size_t read_comma_hex(FILE *f, unsigned char *dest, size_t num) {
rewind(f);
size_t i;
for (i = 0; i<num; i++) {
if (i) {
int ch = fgetc(f);
// Add to tolerate white space before the ',' or after the the last number
while (isspace(ch)) {
ch = fgetc(f);
}
if (ch == EOF) break; // no more data
if (ch != ',') return 0; // Fail, as ',' expected
}
unsigned char hex;
if (fscanf(f, "0x%hhx", &hex) != 1) return 0;
if (dest) dest[i] = hex;
}
return i;
}
void read_comma_hex_file(FILE *f) {
size_t n = read_comma_hex(f, NULL, SIZE_MAX);
if (n == 0) return; // no data or failure
// OP wants an array - research variable length array
const unsigned char LR0[n];
// Alternative: allocate memory instead of using an _array_. (not shown)
// Read data into the array
read_comma_hex(f, LR0, n);
// use LR0 and n some how
for (size_t i = 0; i<n; i++) {
printf("0x%02hhX%s", LR0[i], i > 0 ? "," : "");
}
}

How to save in a string the contents of a text file

This is the code why when I show in output the string I have all words but with in the final row a strange symbol , an ASCII random symbol...
My objective is to save in a string all words to operate with it.
For example I have this document:
Mario
Paul
Tyler
How can i save all words in a string??
#include <stdio.h>
#include <stdlib.h>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int main(int argc, char *argv[]) {
int l,i=0,j=0,parole=0;
char A[10][10];
char leggiparola;
char testo[500];
FILE*fp;
fp=fopen("parole.txt","r");
if(fp!=NULL)
{
while(!feof(fp))
{
fscanf(fp,"%c",&leggiparola);
printf("%c", leggiparola);
testo[j]=leggiparola;
j++;
}
}
fclose(fp);
printf("%s",testo);
return 0;
}
Besides while(!feof(fp)) being "always wrong" you miss to 0-terminate the result string.
To do so place a
testo[j] = '\0'
just after the while-loop.
Instead of using fscanf, try with getc:
int leggiparola; /* This need to be an int to also be able to hold another
unique value for EOF besides 256 different char values. */
...
while ( (leggiparola = getc(fp)) != EOF)
{
printf("%c",leggiparola);
testo[j++] = leggiparola;
if (j==sizeof(testo)-1)
break;
}
testo[j] = 0;
Here's fslurp. I't a bit messy due to the need to grow the buffer manually.
/*
load a text file into memory
*/
char *fslurp(FILE *fp)
{
char *answer;
char *temp;
int buffsize = 1024;
int i = 0;
int ch;
answer = malloc(1024);
if(!answer)
return 0;
while( (ch = fgetc(fp)) != EOF )
{
if(i == buffsize-2)
{
if(buffsize > INT_MAX - 100 - buffsize/10)
{
free(answer);
return 0;
}
buffsize = buffsize + 100 * buffsize/10;
temp = realloc(answer, buffsize);
if(temp == 0)
{
free(answer);
return 0;
}
answer = temp;
}
answer[i++] = (char) ch;
}
answer[i++] = 0;
temp = realloc(answer, i);
if(temp)
return temp;
else
return answer;
}

Extract a column of a list from a text file in C

This may be a simple question with a straightforward answer, but searching through the site I didn't find anything (maybe because I'm new to C programming) except for python codes, which I already wrote and it's quite inefficient.
Suppose I have a list of data in a timestamps.txt file, formatted like this:
<large integer>, <integer between 1 and 8>
<large integer>, <integer between 1 and 8>
and so on (the file is about 4GB)...
What I want to do is to copy only the second column to another file, say singles.txt.
What I did so far works, but it's a rather naive approach and takes too much time. Here's my code:
int main(int argc, char const *argv[])
{
FILE *input_file;
FILE *output_file;
char ch;
int check = 0;
input_file = fopen("timestamps.txt","r");
output_file = fopen("singles.dat","w");
if (!input_file)
return -1;
while((ch = getc(input_file))!=EOF)
{
if(check==1)
{putc(ch,output_file);putc('\n',output_file);}
if(ch == ',')
check = 2;
else
check -= 1;
}
fclose(input_file);
fclose(output_file);
return 0;
}
I'm sure there is a faster way, but I can't seem to make anything work.
Any help would be much appreciated.
Using fgets and fputs is faster than multiple calls to getc and putc, all you need is a buffer (a little buffer in this case) to store the current line:
int main(int argc, char const *argv[])
{
FILE *input_file;
FILE *output_file;
char buf[128];
char *ptr;
input_file = fopen("timestamps.txt","r");
output_file = fopen("singles.dat","w");
if (!input_file)
return -1; /* use EXIT_FAILURE instead of -1 */
/* you forget to check output_file */
while (fgets(buf, sizeof buf, input_file)) {
ptr = strchr(buf, ','); /* find the comma */
if (ptr != NULL) {
fputs(ptr + 1, output_file); /* +1 to skip the comma */
}
}
fclose(input_file);
fclose(output_file);
return 0;
}
Your idea isn't so bad, but you should make your variable check either 0 or 1, depending on whether you want to copy the current input data or not. And you must reset the check with each new line.
Alternatively, you could countthe current field your are in and copy the data when the field is the one you want.
Here's a version that copies the column want delimited by sep verbatim to the output file:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char const *argv[])
{
FILE *in = stdin;
FILE *out = stdout;
int want = 1;
int col = 0;
int sep = ',';
for (;;) {
int c = getc(in);
if (c == EOF) break;
if (c == sep) {
col++;
} else if (c == '\n') {
col = 0;
putc(c, out);
} else if (col == want) {
putc(c, out);
}
}
return 0;
}
(I've used stdin and stdout, because I was lazy and didn't want to do the flie opening and closing stuff.)

Resources