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;
}
Related
I have a text file, and I open it and read one line of it, and close the text file. I'm calling my function under a for loop, but each time this function reads the first line of a text file, how can I fix it to read from the continuation
You can use fseek to reposition yourself in the file after closing and reopening, but it is very unusual to do so. So unusual, in fact, that I would suggest it is completely wrong. Here's some sample code that demonstrates how to do that, as well as a more typical loop. Each loop here reads the first 2 lines of the file, assuming each line is sufficiently small; handling long lines is beyond the scope of this question.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
FILE * xfopen(const char *path, const char *mode);
void xfseek(FILE *stream, long offset, int whence, const char *);
long xftell(FILE *stream, const char *);
void xfclose(FILE *stream, const char *);
int
main(int argc, char *argv[])
{
const char *path = argc > 1 ? argv[1] : "input";
/* Read the first two lines of the file, closing the file on each
* iteration. This is ** not ** the usual way to do this, and is
* included here for demonstration
* purposes only. DO NOT DO THIS.
* It is very unusual to close and re-open the file on each iteration.
*/
long position = 0;
for( int line = 1; line < 3; line++ ){
FILE *ifp = xfopen(path, "r");
char buf[1024];
xfseek(ifp, position, SEEK_SET, path);
fgets(buf, sizeof buf, ifp); /* (1) */
printf("line %d: %s", line, buf);
position = xftell(ifp, path);
xfclose(ifp, path); /* !! */
}
/* The more usual way to read each line of a file is to simply
* read it with repeated calls to the appropriate read method
* (fgets, fread, fgetc, etc.) Each subsequent read starts
* where the previous read finished.
*/
FILE *ifp = xfopen(path, "r");
for( int line = 1; line < 3; line++ ){
char buf[1024];
fgets(buf, sizeof buf, ifp); /* (1) */
printf("line %d: %s", line, buf);
}
xfclose(ifp, path);
return 0;
}
FILE *
xfopen(const char *path, const char *mode)
{
FILE *fp = path[0] != '-' || path[1] != '\0' ? fopen(path, mode) :
*mode == 'r' ? stdin : stdout;
if( fp == NULL ){
perror(path);
exit(EXIT_FAILURE);
}
return fp;
}
void
xfseek(FILE *stream, long offset, int whence, const char *name)
{
if( fseek(stream, offset, whence) == -1){
perror(name);
exit(EXIT_FAILURE);
}
}
long
xftell(FILE *stream, const char *name)
{
long ret = ftell(stream);
if( ret == -1 ){
perror(name);
exit(EXIT_FAILURE);
}
return ret;
}
void
xfclose(FILE *stream, const char *name)
{
if( fclose(stream) ){
perror(name);
exit(EXIT_FAILURE);
}
}
Notes: (1) It is left as an exercise for the reader how best to handle short reads (eg, when fgets returns NULL) or long lines (eg, when fgets completely fills the buffer but fails to read an entire line). Perhaps it is a bit of a cop-out to leave that as an exercise, but the annoyance of dealing with those issues points strongly towards reasons for using the standard idiom. If you want to print the first two lines of the file, use some variation of for( int count = 0; (c = fgetc(fp)) != NULL && count < 2; ) { if( c == '\n' ) count += 1; putchar(c); }. Putting the read function as a condition of the loop is (almost) always the best choice.
The comments have already made suggestions on other alternatives for what you are attempting. But regardless whether it is the right approach or not, it seems pretty clear that your stated ask is clear about wanting to use fseek() et. al to view successive lines when opening and closing a file.
To open and close a file, and each time access and display a successive line, you must first know where each of the locations to be viewed are located within that file. Indeed, as you have tagged, fseek(), (as well as ftell()) can be used to do this. The following pseudo code steps illustrate one possibility:
//store file pointer locations of each line in file:
FILE *fp = fopen(fn, "r");
if(fp)
{
for(int i = 0; i < l_cnt; i++)
{
pos[i] = ftell(fp);
fgets(line, sizeof line, fp);
}
}
fclose(fp);
Then...
//alternately open and close file to view successive lines at stored positions
for(int i = 0; i < line_cnt; i++)
{
FILE *fp = fopen(fn, "r");
if(fp)
{
fseek(fp, pos[i], 0);
fgets(line, sizeof line, fp);
printf("line %d: %s\n", i, line);
fclose(fp);
}
}
There is a more complete source and run-time example here
I try to read a file line by line to that dynamic array:
//r = rows (max. chars of one line), c = column (lines of file)
char *file_content[r];
for (int i=0; i<r; i++) {
file_content[i] = (char*)calloc(c,sizeof(char));
}
readfile.c
void readFile(char *file_name, char **file_content) {
char const* const fileName = file_name;
FILE* file = fopen(fileName, "r");
int i = 0;
while(fgets(file_content[i], 512 + 1, file)) { //512+1 for null termination
/* get rid of ending \n from fgets */
file_content[i][strlen(file_content[i]) - 1] = '\0';
i++;
}
fclose(file);
}
So this code works perfectly with a static array like file_content[500][500] but with my dynamic array from above a
printf("%s", file_content[0]);
prints random content of the file.
I don't know how I should debug my problem, I'm a beginner..
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;
}
I'd like to make copy of my binary file, but I need to make it from hex representation of my binary file.
In the first program I create txt file with with hex representation of my binary file:
#include <stdio.h>
#include <stdlib.h>
const int BYTE = 1;
int counter = 0;
int read;
long size;
FILE *file1 = NULL;
FILE *file2 = NULL;
fpos_t length;
int main() {
unsigned char hex[3];
unsigned char buffer[1];
file1 = fopen("server.pdf", "rb");
fseek(file1, 0, SEEK_END);
fgetpos(file1, &length);
size = length.__pos;
fseek(file1, 0, SEEK_SET);
if (file1) {
file2 = fopen("test.txt", "w");
while (counter < size) {
read = fread(buffer, 1, BYTE, file1);
counter += read;
i = 0;
while(i<read) {
sprintf(hex, "%02x", (unsigned int) buffer[i++]);
fwrite(hex, 1, BYTE, file2);
}
}
} else
printf("ERROR");
fclose(file1);
fclose(file2);
}
In the second, I read data from txt file and after that I write it to binary file:
#include <stdio.h>
FILE *file1;
FILE *file2;
int size;
fpos_t length;
int main(){
file1 = fopen("test.txt", "r");
fseek(file1, 0, SEEK_END);
fgetpos(file1, &length);
size = length.__pos;
fseek(file1, 0, SEEK_SET);
char buffer[1];
char hex[3];
int counter = 0;
int read;
if(file1){
file2 = fopen("test.pdf", "wb");
while (counter < size) {
read = fread(hex, 1, 3, file1);
counter += read;
sscanf(hex, "%02x", buffer);
fwrite(buffer, 1, 1, file2);
}
}
fclose(file1);
fclose(file2);
}
Unfortunately I can't open my copy. What is the reason?
Have you looked at the files content? You wont be able to sprintf the hex representation to the variable hex since it's 1 byte in size.
The variable hex is declared hex[BYTE] where BYTE = 1, but your sprintf format string looks like this: "%02x" ie 2 bytes, then you need room for a terminating zero.
The same goes for when you write to the file, you only write 1 byte from your hex string.
Declaring a variable as: var[1] is pointless you can achieve the same thing with var btw.
Besides this you should also add proper error handling, if you can not successfully open the file. This means checking the file pointer after your call to fopen, then take an appropriate action. perror() will print an error string that corresponds to errno, and in case of a file that does not exist it will print something like: "no such file or directory" or similar.
When you said you can't open your copy, you mean you have an error in fopen("test.txt", "r")? Did you check errno value? Check perror() and strerror().
Besides, you have no loop in second program.
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.