FILE *fp;
char *f_array[256];
int f_length;
int *a = 0;
fp = fopen("test.txt", "r");
fseek(fp, 0, SEEK_END);
f_length = ftell(fp);
printf("%d\n\n", f_length);
int n = 1, i = 0;
while (n > 0)
{
n = fscanf(fp, "%s", f_array[i]);
i++;
}
I am trying to copy the contents of a .txt file into a char* array. Much like what would happen with InternetReadFile and lpbuffer. However, I cannot seem to get this right. I need my array to be filled with the contents of the .txt file character by character. Any suggestions?
I need the array to be single-dimensional
The issue is mainly to do with your data types. You want to store the file in memory. That would be a character (byte) array, but you have created an "array of pointers":
char *f_array[256];
When you probably wanted just:
char f_array[256];
Then, to do as you asked and read character by character into that array, use fgetc. Note that fgetc will be far less efficient that just reading the whole file in a single function call with fread. The kernel:
while ( EOF != (c = fgetc( fp )) && ++i < MAX_LEN )
f_array[ i ] = c;
In context of a working example:
#include <stdio.h>
int main ( ) {
const size_t MAX_LEN = 255;
FILE * fp;
char f_array[ MAX_LEN +1];
int c;
size_t i = -1;
f_array[ MAX_LEN +1] = 0;
fp = fopen("test.txt","r");
if ( NULL == fp )
perror("Error opening file");
else {
while ( EOF != (c = fgetc( fp )) && ++i < MAX_LEN )
f_array[ i ] = c;
fclose (fp);
}
f_array[ i ] = 0;
printf("%zu bytes read\n\n", i);
printf("Content read:\n%s\n", f_array);
return 0;
}
You are calculating the length of the file but you don't use this information in
any way.
char *f_array[256];
This is an array of dimension 256 of pointers to char. f_array[i] is
uninitialized and it's pointing into the digital nirvana, passing it to
fscanf yields undefined behaviour. You would need to declare it as something
like this:
char f_array[255][255];
But then you are limiting yourself to max 255 strings, you are not storing it
into a single string. Also you are storing max. 255 words. Use fgets or
fread to get the whole content at once.
char file[f_length + 1];
rewind(fp);
fread(file, f_length, 1, fp);
file[f_length] = 0; // terminate the string
printf("Whole file is: %s\n", file);
Here you are storing the whole file in an array of chars. Also after setting
the file at the end, you'll need to rewind the file to the beginning, otherwise
you are not reading anything.
Related
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 ? "," : "");
}
}
I am trying to understand how to read some file from text, and then enter it into an array to save it for later manipulation. I just cant seem to get it. I have tried structs and string arrays but I still cant grasp how to implement this in c.
I have successfully been able record at least one line into the array but it copies the same line multiple times. Here is a layout of what my text and code look like.
Text File:
# A demonstration of some simple MIPS instructions
Loop: sll $t1, $s3, 2
add $t1, $t1, $s6
lw $t0, 0($t1)
bne $t0, $s5, Exit
addi $s3, $s3, 1
j Loop
Exit:
.c File:
int assem::readFile(FILE *file) //read file function for file to be read
{
//char String[200];
char lines[20];
char *ptr = lines;
const int MAX = 101;
char myString[MAX];
int i = 0;
while(fgets(&lines[i], 100, file) != NULL)
{
i++;
}
printf("%s\n", lines);
char * fgets ( char * str, int num, FILE * stream );
fgets() reads characters from stream and stores them as a C string into str until (num-1) characters have been read or either a newline or the end-of-file is reached, whichever happens first.
I have successfully been able record at least one line
Because a newline character makes fgets stop reading. See reference here.
You can use
size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );
to read from a file.
fread() reads an array of count elements, each one with a size of size bytes, from the stream and stores them in the block of memory specified by ptr.
I write the following function to read from a file and write each character into a buffer, which may help you:
typedef unsigned char BYTE;
void readFile(char *filename, BYTE* buffer) {
FILE * pFile;
long lSize;
size_t result;
pFile = fopen(filename, "rb");
if (pFile == NULL ) {
fputs("File error", stderr);
exit(1);
}
// obtain file size:
fseek(pFile, 0, SEEK_END);
lSize = ftell(pFile);
rewind(pFile);
// copy the file into the buffer:
result = fread(buffer, 1, lSize, pFile);
if (result != lSize) {
fputs("Reading error 2", stderr);
exit(3);
}
/* the whole file is now loaded in the memory buffer. */
fclose(pFile);
}
Here's a simple code to statically store 10 lines containing 99 characters (don't forget \0 to terminate a string)
const size_t maxLines = 10;
size_t currentLine = 0;
char lines[maxLines][100]; // Storing 10 lines
// Reading and storing a line from file
while(fgets(lines[currentLine], sizeof(lines[currentLine]), file) && currentLine < maxLines)
{
++currentLine;
}
// Printing stored lines
size_t i = 0;
while (i < currentLine)
{
printf("%s", lines[i]);
++i;
}
You need to read all the file character by character. It will make it easier.
#include <stdio.h>
void main ()
{
int ch, size, i = 0;
FILE *file;
file = fopen("Text.txt", "r"); // open the file for reading
fseek(file, 0L, SEEK_END); // goto the end of the file
size = ftell(file);
rewind(file); // goto the start of the file
char *text = (char*)malloc(size - 20); // the -20 is to avoid the gibberish at the end of the text file
for (i = 0; i<size; i++)
{
ch = fgetc(file);
text[i] = ch;
}
printf("%s", text);
getchar();
}
Thanks for the help> i managed to solve figure out how to do it a bit earlier. Here is my implementation after I finally understood a few more c literals. Thanks AGAIN!!!
"counter" keeps track of how many lines are in the text file
int assem::readFile(FILE *file)
{
int i =0;
counter = 0; //this is sort of the constructor, if you will.
//breaks down text file into line by line
while(fgets(myString, 101, file) != NULL) //and stores them into "myLines array"
{
myLines[i] = strdup(myString);
i++;
counter++;
}
return 0;
}
I'm quite new to C programming and have just begun studying files. I'm wondering whether it is possible to read a file line by line (including spaces in each line) into an array of size equal to the number of lines in the file. I really have no idea where to start or whether this is even possible so any guidance at all would be much appreciated.
Example
A text file in the form of:
Computer Programming
Software Engineering
Computer Architecture
to be written into array such that:
char array[4];
array[0] = "Computer Programming";
array[1] = "Software Engineering";
array[2] = "Computer Architecture";
All I have so far is:
int main()
{
char array[50];
bool answer;
FILE *classes;
classes = fopen("classnames.txt", "r");
if(classes == NULL){
printf("\n ************* ERROR *************\n");
printf("\n \"classnames.txt\" cannot be opened.\n");
printf("\n PROGRAM TERMINATED\n");
exit(EXIT_FAILURE);
}
And next I would like to write each class name into each element of the array.
Yes, you just have to declare array as char** and dynamically allocate as you read each line. E.g.
int MAX_NUM_LINES = 1000;
int MAX_LINE_LEN = 256;
char** array;
malloc(array, MAX_NUM_LINES*sizeof(char*));
fp = fopen(...);
int line_ct = 0;
char line[MAX_LINE_LEN];
while ( fgets(line, MAX_LINE_LEN, fp) != NULL )
{
int len = strlen(line);
malloc(array[line_ct], len * sizeof(char));
strcpy(array[line_ct], line);
line_ct++;
}
I have not actually tried to compile this code, but something like this will work. You can also replace MAX_NUM_LINES with the actual value by doing a quick runthrough first and counting the lines--that would be preferable probably.
This is an example of a possible approach
#include <stdio.h>
#include <string.h>
int main()
{
char array[100][100];
char line[100];
size_t arraySize;
size_t count;
FILE *file;
const char *filepath;
filepath = "<put the file path here>";
file = fopen(filepath, "r");
if (file == NULL)
{
perror("fopen()");
return -1;
}
count = 0;
arraySize = sizeof(array) / sizeof(array[0]);
while ((fgets(line, sizeof(line), file) != NULL) && (count < arraySize))
{
size_t length;
length = strlen(line);
if (line[length] == '\0')
line[--length] = '\0';
memcpy(array[count++], line, 1 + length);
}
fclose(file);
return 0;
}
I'm trying to loop over each character of a line within fgets, but I am running into errors, as I'll explain below.
int main(int argc, char* argv[]) {
char arr[200]
int currS = sizeof(arr) / sizeof(char);
// call readIt function
}
void readIt(char* argv[], char arr[], int currS) {
FILE* file;
file = NULL;
file = fopen(argv[1], "r");
while(fgets(arr, currS, file) != NULL)
for (int i = 0; i < sizeof(arr); i++)
print each char of current line
}
When I do the for loop over each line, each line output will be the length of the very FIRST line in the file. The # of times the for loop iterates never changes. How do I update it? I looked at other SO questions but they aren't very helpful..
In the readIt() function, you need strlen(arr), not sizeof arr. The latter will give you the size of a char *, which is always the same, regardless of the length of the string to which it might point.
You should also check that the return from fopen() is not NULL, since fopen() can fail for many reasons.
void readIt(char* argv[], char arr[], int currS) {
FILE * file = fopen(argv[1], "r");
if ( file ) {
while( fgets(arr, currS, file) ) {
const int len = strlen(arr);
for ( int i = 0; i < len; ++i ) {
// print each char of current line
}
}
}
}
Note that using the variable len here means you only calculate the length of the string once, before you start to loop over it, rather than calculating it every time through the loop which would happen if you did for ( int i = 0; i < strlen(arr); ++i ). If all you're doing is printing every character, then the length of the string isn't going to change in between calls to fgets(), so it's inefficient to calculate it more than once.
Also, unless for some reason you want the array in main() to contain the last line read from the file after readIt() returns, you could more easily define arr within readIt() itself, to avoid the need to pass it to that function at all, for instance:
void readIt(char* argv[]) {
FILE * file = fopen(argv[1], "r");
if ( file ) {
char arr[200];
while( fgets(arr, sizeof arr, file) ) {
const int len = strlen(arr);
for ( int i = 0; i < len; ++i ) {
// print each char of current line
}
}
}
}
Because arr is now an actual array within readIt(), rather than a pointer to char (you can't pass an array to a function, only the address of one), sizeof arr will give you the actual size of the array, rather than the size of a char *, so you can pass that to fgets().
This function:
void readIt(char* argv[], char arr[], int currS) {
FILE* file;
file = NULL;
file = fopen(argv[1], "r");
while(fgets(arr, currS, file) != NULL)
for (int i = 0; i < sizeof(arr); i++)
print each char of current line
}
would be better written to use the actual number of characters in the arr[]
Suggest using braces, to avoid many future maintenance headaches
Suggest using vertical spacing for readability
Suggest using comments to avoid many future maintenance headaches
void readIt(char* argv[], char arr[], int currS)
{
FILE* file = NULL;
if( NULL == (file = fopen(argv[1], "r") ) )
{ // then fopen failed
perror( "fopen failed" );
exit( EXIT_FAILURE );
}
// implied else, fopen successful
// read line from file and echo to user
// note: file lines are considered to be terminated by either a NUL char or newline or EOF
// fgets() assures the line in arr[] has a NUL char termination
while( fgets(arr, currS, file) )
{
int len = strlen(arr); // returns offset to NUL char
// use following if do not want to echo a newline read from the file
if( '\n' == arr[strlen(arr)-1])
{
arr[strlen(arr)-1] = '\0';
len--;
} // end if
printf( "\nNumber of characters in line: %d\n", len );
printf( "%s\n", arr );
} // end while
fclose(file); // cleanup
} // end function: readIt
I have the following code that converts a stream data of 16-bit integer to unsigned 8-bit integer.
I am looking to convert them to alphabetical data values and see what they contain.
#include<stdio.h>
int main() {
FILE *fp,*out;
char buffer[256];
size_t i = 0;
fp=fopen("c:/Gosam/input.txt", "rb");
if(fp != NULL) {
fread(buffer, sizeof buffer,1, fp);
}
out = fopen("c:/Gosam/res.txt", "w");
if(out != NULL) {
// buffer = (char*) malloc (sizeof(char)*Size);
for( i = 0; i < sizeof(buffer); i += 2)
{
const unsigned int var = buffer[i] + 256 * buffer[i + 1];
fprintf(out, "%u\n", var);
}
fclose(out);
}
fclose(fp);
}
The following is the form of my output:
263 4294966987 4294967222 4294967032 64 4294967013 73 4294967004 90
4294967028 83 4294966975 37 4294966961 5 4294966976 82 4294966942
4294967022 4294966994 11 4294967024 29 4294966985 4294966986 4294966954 50
4294966993 4294966974 4294967019 4294967007
This are the values I want to convert to alphabetical characters and see their content.
I don't know what you expect as an answer (you didn't ask a question), but there seems to be one suspicious thing in your code:
char buffer[256];
Here char means signed char. If your code does manipulations on them (like multiplying by 256), it probably doesn't do what you expect (though I can only guess what you expect - your question doesn't mention it).
Try the following:
unsigned char buffer[256];
Also please ask a question (that is, something with a question mark), and give some examples (input, output).
Your basic mistakes were:
after opening the inputfile checking out instead of fp against NULL
fread until eof won't return the number of characters that could be read (I've used fseek and ftell for this purpose)
writing uint values instead of char values to your file
I've fixed them and commented the affected lines appropriate. I also changed the buffer to use dynamic memory allocation instead of static allocation (that's how you can allocate memory for a buffer of a size that is unknown at compile-time). Please try the following code, which will copy all ASCII characters from one file to your output file (which is probably what you meant by 'alphabetical strings'):
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[]){
FILE *fp, *out;
char *buffer = NULL; /* use a pointer for dynamic memory allocation */
size_t i = 0, charCount = 0;
fp = fopen("c:/input.txt", "r"); /*read as ascii - not binary */
if(fp != NULL){ /*use 'fp' here 'out' is not initalized */
fseek(fp, 0, SEEK_END); /* go to end of the file */
charCount = ftell(fp) - 1; /* get position */
fseek(fp, 0, SEEK_SET); /* return to the beginning of the file */
buffer = (char*)malloc(sizeof(char)*charCount); /* allocate memory */
fread(buffer, sizeof(char) * charCount, 1, fp); /* reads all characters from the file */
}
out = fopen("c:/output.txt", "w");
if(out != NULL){
for(i = 0; i < charCount; i += 1){ /* loop from 0 to count of characters */
const unsigned char var = buffer[i];
fprintf(out, "%c", var);
}
fclose(out);
}
fclose(fp);
if(buffer != NULL){
free(buffer); /* deallocate memory */
}
return 0;
}