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 ? "," : "");
}
}
Related
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;
}
I just need to know how to pass and declare a FILE* array into a function
void openInputFiles(char* name, FILE* input[]){
char filename[10];
if (strcmp("average", name) == 0){
int i;
int k =1;
for (i=1;i<=10;i++){
if (i<10){
sprintf(filename,"%s_00%d",name,k);
}
if (i == 10){
sprintf(filename,"%s_0%d",name,k);
}
input[i-1] = fopen(filename,"r");
k++;
}
}
if (strcmp("median", name) == 0){
int i,k;
k=1;
for (i=1;i<10;i++){
sprintf(filename,"%s_00%d",name,k);
input[i-1] = fopen(filename,"r");
k++;
}
}
}
That's the code for the function and this is where I am trying to call it
int main(int argc, char* argv[]){
FILE* input[10];
openInputFiles(argv[1],input);
}
I don't get any warnings when I compile this but when I try to gdb it to test what's wrong it's seeming that the FILE* isn't allocating a memory address to input[0] because it says its at address 0x0. What am I doing wrong?
char filename[10];
...
sprintf(filename,"%s_00%d",name,k);
As user3121023 correctly noted, there isn't enough space to fit "average_001" into the 9 characters (plus terminating NUL) that you've allocated for the filename. You need to make it char filename[12]; or bigger. As a result, your program exhibits undefined behavior, which means anything could happen.
You should also ~never use sprintf -- use snprintf instead, and always check for errors, like this:
if (snprintf(filename, sizeof(filename), "%s_00%d", name, k) >= sizeof(filename)) {
abort(); // filename is too short.
You can also simplify your loops (there is absolutely no need to handle i == 1 through 9 differently from i == 10:
for (i = 0; i < 10; i++) {
int n = snprintf(filename, sizeof(filename), "%s_%03d", name, i + 1);
if (n == -1 || n >= sizeof(filename) {
// handle format error or "filename" too short here.
}
input[i] = fopen(filename, "r");
if (input[i] == NULL) {
// handle fopen failure here.
}
}
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;
}
I am trying to write a program that takes the words from a file, and puts those in a dynamic array. However when I try to run my code the program copies it all except for the spaces. How do I fix this?
This is a test does it work?
But I get the following:
Thisisatestdoesitwork?
char** getWords(char* filename, int* pn){
char** tmp = (char**)malloc( 1000*sizeof(char));
int *temp=(int*)malloc(1000*sizeof(int);
int c;
int counter = 0;
FILE* fileInput = fopen(filename, "r");
if(fileInput == NULL){
return tmp; // return if file open fails
}
while((c=fgetc(fileInput)) != EOF){
result = fscanf(fileInput, "%c", &c); //try to read a character
if(isalpha(c)){ //chararect alphabetical
tmp[counter] = c; // safe int to array
counter ++;
printf("%c", c); fflush(stdout);
}
else{ // if read not succesfull
fscanf(fileInput, ""); // needs to scan anything not a character
}
if(counter > 100){ // to not exceed the array
break;
}
if(feof(fileInput)){ // to check if at the end of the file
break;
}
}
fclose(fileInput); // closing file
*pn = counter;
return tmp;}
My main Function:
int main(int argc, char* argv[]){
int n;
char** a = getWords("opdracht_4_5.c", &n);
if (a != NULL){
puts("gevonden woorden:");
for (int i = 0;i < n; i++){
printf("%3d %s\n",i,a[i]);
}
for (int i = 0;i < n; i++){
free(a);
}
free(a);
}
return (EXIT_SUCCESS);
}
There are quite a few problems with your code. Here's a start:
You don't test the return value of fopen().
You don't test the return value of malloc().
You assign the return value of fgetc() to a variable of type char. Plain char is compatible with either signed char or unsigned char. In order to make a distinction between a character and EOF (which is negative), the fgetc() function returns a character converted to unsigned char (or EOF). You need to test for EOF and then convert the value to a plain char.
The is...() function expects an int argument whose value is in the range of an unsigned char or EOF. If you have a plain char, you first have to cast it to unsigned char, or you can pass the return value of fgetc() straight to isalpha().
You attempt to append an zero-length char array (temp) to an uninitialized char array (s), and you do not test if there is enough room in the target array. This is broken for more reasons than than I care to enumerate.
You allocate memory for an array of 1000 pointers to char, but you never allocate memory for the char pointers themselves.
You try to append your buffer (s) to an uninitialized pointer (*tmp).
You call strlen() on something that is not null-terminated.
You never return the length of the array.
You call a number of functions that have not been declared.
This will read the file, put each word in an array
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
char** getWords(char* filename, int* pn){
char input[100]; // array to hold each word
char** tmp; // double pointer
int counter = 0;
int words = 0;
int c;
tmp = malloc( (*pn)*sizeof(char*)); // allocate pointers for number of words
if ( tmp == NULL) {
printf ( "malloc failed\n");
exit (1);
}
FILE* fileInput = fopen(filename, "r");
if(fileInput == NULL){
printf ( "file open failed\n");
*pn = 0; // no words entered
return tmp; // return if file open fails
}
while(( c = fgetc(fileInput)) != EOF){
if( isalnum(c)){ // is alpha or number
input[counter] = c; // save to array
input[counter + 1] = '\0'; // save a \0 to the end to make a string
counter ++;
}
else{ // not alpha or number
if ( counter > 0) { // if there are characters, save the word
tmp[words] = malloc ( strlen ( input) + 1); // memory for this word
strcpy ( tmp[words], input); // copy the word to the array
words++;
counter = 0;
if ( words >= *pn) { // got all the words wanted
break;
}
}
}
if(counter > 98){ // too many characters for input, start a new word
tmp[words] = malloc ( strlen ( input) + 1);
strcpy ( tmp[words], input);
words++;
counter = 0;
if ( words >= *pn) {
break;
}
}
}
fclose(fileInput); // closing file
*pn = words; // save number of words
return tmp;
}
int main(int argc, char* argv[]){
int n;
int i;
printf ( "enter the number of words to obtain\n");
scanf ( "%d", &n);
char** a = getWords("opdracht_4_5.c", &n);
if (a != NULL){
puts("gevonden woorden:");
for ( i = 0;i < n; i++){
printf("%3d %s\n",i,a[i]);
}
for ( i = 0;i < n; i++){
free(a[i]); // free each word
}
free(a); // free the pointer to the words
}
return (EXIT_SUCCESS);
}
The input file I used had these as the first two lines
#include<stdio.h>
#include<string.h>
I get this output:
enter the number of words to obtain
6
gevonden woorden:
0 include
1 stdio
2 h
3 include
4 string
5 h
This answer is as yet incomplete
Please allow me to finish this before commenting on it -- Thank you
There are a lot if issues with your code, I won't clean it up for you. However I would like to give you some hints on how your program SHOULD be coded:
Your main objective is to read a file and load the content word by word in an array.
Sorting is an incorrect use because that implies you want to sort them alphabetically or in some other order after loading it into an array.
Okay, so first things first, let's figure out the overall operation of our program. We'll call our program kitten, because it's not quite as powerful as cat.
To run our program we will assume that we give it the filename we want to read on the command-line as follows:
$ ./kitten somefile.txt
and expect the output to be:
word1
word2
word3
.
.
.
wordN
Total words: N
So, let's get started, first we make sure that our user specifies a filename:
#include <stdio.h>
int usage(const char *progname);
int main(int argc, char *argv[])
{
if (argc < 2) {
usage(argv[0]);
return -1;
}
return 0;
}
int usage(const char *progname)
{
fprintf(stderr, "Usage is:\n\t%s filename\n", progname);
}
Now that we know that our program can get a filename, let's try to open the text file, if there is an issue with it we use perror to display the error and exit the program, otherwise we are ready to use the file:
#include <stdio.h>
#include <errno.h>
int usage(const char *progname);
int main(int argc, char *argv[])
{
FILE *fp;
if (argc < 2) {
usage(argv[0]);
return -1;
}
fp = fopen(argv[1], "r");
if (!fp) {
perror(argv[1]); /* display system error, with the filename */
return -1;
}
/* TODO: file manipulation goes here */
fclose(fp); /* close the file */
return 0;
}
int usage(const char *progname)
{
fprintf(stderr, "Usage is:\n\t%s filename\n", progname);
}
Now in C each function should perform just one task. The task should make human sense. For example if the function is supposed to read words into an array, then that's all it should do, it should not open a file or close a file, which is WHY the code above does not create a function for opening the file the way you did. Your function should take in FILE * as the file to read.
Because we use the FILE * as input we'll start the function name with an f to keep with the stdio convention. Ideally, the function should take a pointer to char * (strings) to store the words in.
#include <stdio.h>
#include <errno.h>
int usage(const char *progname);
size_t fload(FILE *fp, char **wordlist_p);
int main(int argc, char *argv[])
{
FILE *fp;
if (argc < 2) {
usage(argv[0]);
return -1;
}
fp = fopen(argv[1], "r");
if (!fp) {
perror(argv[1]); /* display system error, with the filename */
return -1;
}
if(fload(fp, wordlist_p) < 0) {
fprintf(stderr, "Something went wrong\n")
}
fclose(fp); /* close the file */
return 0;
}
int usage(const char *progname)
{
fprintf(stderr, "Usage is:\n\t%s filename\n", progname);
}
size_t fload(FILE *fp, char **wordlist_p)
{
size_t rv = -1; /* return value */
return rv;
}
Now we run into a conceptual problem. How do we allocate memory for wordlist_p? I mean we don't have any idea about how big the file is, we also don't know how big the biggest word in the file is.
Crude approach
Let's first try an think about it the simple way:
Point to the beginning of the `wordlist_p` with a `tail_pointer`
Read the file line by line, (we assume no hyphenation)
For each line split the line up along white spaces,
Allocate space for the number of words in the `wordlist_p` array
For each word in the split line
Allocate space for the word itself
Save the pointer to the word at the tail_pointer
Advance wordlist_p tail_pointer
Next word
Next Line
Let's look at what the fload function would look like with these steps above,
More to come ##
I need to put a string (from a file) in a matrix and print out the result. I have some issue in understanding the right way to do this so:
#include <stdio.h>
#include <string.h>
int main (int argc, char *argv[])
{
const int MAX = 50;
char mat[MAX][MAX];
char str[MAX];
char word[MAX];
int row = 0;
int i = 0;
FILE * fp;
fp = fopen ("file.txt", "r");
if (fp == NULL)
printf ("Error!\n");
while (fgets(str, MAX, fp) != NULL)
{
sscanf (str, "%s\n", word);
strcpy(mat[i][0], word);
row++;
}
for (i = 0; i <= row; i++)
{
puts(mat[i][0]);
}
return 0;
}
I'm obliviously doing something wrong but... what?
I have a file like this:
One
Two
Three
Four
Five
Six
Hello
If you compile this with gcc, it will give you two warnings: each warning points to one of the three major errors in the code:
main.c: In function 'main':
main.c:24: warning: passing argument 1 of 'strcpy' makes pointer from integer without a cast
main.c:31: warning: passing argument 1 of 'puts' makes pointer from integer without a cast
Each of those line numbers -- 24 and 31 -- is a line where you're using mat[i][0], which is a character, when you should instead use mat[i], which is a character array. Fix those, and then there's just one problem: you use i, which is always 0, in the while loop. Use row, which is incremented as the row progresses, and the program should work exactly as designed.
There are a couple of other things I would change to improve the program: your while loop reads a string into one buffer, copies it into a second buffer, then copies it into the matrix; you could just scan it directly into the matrix and be done with it!
A matrix usually contains numbers. Yours contains chars. There are problems with your code but to get a good answer you should tell us the format of the file you are reading (maybe paste a small one in your question).
EDIT:
This file contains an array of strings separated by newline. You can read it like this (if the strings don't have any whitespace in them):
while (fscanf(fp, "%s\n", mat[row]) > 0)
{
row++;
}
for (i = 0; i <= row; i++)
{
printf( "%s\n", mat[i]);
}
You should copy the string to the element of matrix with the given index. You should pass the pointer to the first element of matrix to strcpy(i.e. remove the [0]).
Do something like:
while (fgets(str, MAX, fp) != NULL)
{
sscanf (str, "%s\n", word);
strcpy(mat[i], word);
row++;
}
EDIT: also when printing the strings use only mat[i] not mat[i][0].
I have done some changes to your code. First lets pin point your mistakes.
char mat[MAX][MAX]; will not serves your intention of creating string matrix.
It is unnecessary to do read sscanf (str, "%s\n", word);. Already you read it from file. you can directly use it.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main (int argc, char *argv[])
{
const int MAX = 50;
char *mat[MAX][MAX];
char str[MAX];
int i = 0, j = 0;
int now = 0;
FILE * fp;
fp = fopen ("file.txt", "r");
if (fp == NULL)
printf ("Error!\n");
while (fgets(str, MAX, fp) != NULL)
{
//sscanf (str, "%s\n", word);
mat[i][j] = malloc(sizeof(str));
strcpy(mat[i][j], str);
j++;
now++; //Tracks no.of elements
if(j == MAX)
{
j = 0;
i++; //store in next row
}
}
for (i = 0; i < MAX; i++)
for (j = 0; j < MAX; j++)
{
if(now == 0)
break;
now--;
puts(mat[i][j]);
free(mat[i][j]);//Avoids memory leak
}
return 0;
}