guys i want to read the text from my file and assign every character to a single element of the array
char A[1000];
FILE * fpointer;
fpointer=fopen("text.txt","r");
i=0;
while(!feof(fpointer))
{
fscanf(fpointer,"%c",&A[i]);
i=i+1;
}
fclose(fpointer);
for (i=0;i<100;i++)
{
printf("%c",A[i]);
}
return 0;
but the problem is that the output is some weird symbols instead of the file's text which is "This is just a test".Why is that happening ?
Possible reasons include:
fopen failed to open the specified file. Fix by checking the return value of fopen.
See Why is “while ( !feof (file) )” always wrong?
You always print 100 characters, but if the file contains less than 100 characters, you're in trouble because you print uninitialized locations of the array, leading to UB. Fix by printing everything starting from zero upto i.
Corrected code snippet:
int i = 0, j = 0;
char A[1000];
FILE* fpointer;
fpointer = fopen("text.txt", "r");
if(!fpointer)
{
fputs("fopen failed! Exiting...\n", stderr);
exit(-1); /* Requires `stdlib.h` */
}
while(fscanf(fpointer, "%c", &A[i]) != EOF)
{
i = i + 1;
}
fclose(fpointer);
for (j = 0; j < i; j++){
printf("A[%d] = '%c'\n", j, A[j]);
}
To expand on the points by #Cool Guy:
In case your files do not contain the null character, you can avoid using another variable to store the number of characters read. If you null terminate your read in characters, you can just print them directly as a string.
You have to make sure that A can hold enough characters. If you expect at most 1000 characters, make sure that A has a size of 1001 bytes to contain the terminating NUL character.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
char A[1001] = { 0 }; /* init to NUL, expect at most 1000 chars */
int i;
FILE *fpointer;
fpointer=fopen("text.txt","r");
if(!fpointer) {
perror("Error opening file"); /* print error message */
exit(-1); /* Requires `stdlib.h` */
}
/* read all characters from fpointer into A */
for (i=0; fscanf(fpointer, "%c", &A[i]) != EOF; i++);
fclose(fpointer);
printf("%s\n",A); /* print all characters as a string */
/* alternatively, loop until NUL found */
for (i=0; A[i]; i++)
printf("%c", A[i]);
printf("\n");
return 0;
}
Related
I've written a simple config parser using fscanf and now want to add a comment character (#).
My configuration file contains three columns of which fscanf reads and stores in their corresponding arrays. This works well, but I'm a little unsure how to write it so that "if the character read is # then move onto the next line.
I've tried using fgetc but that seems to only read the first character, and it appears to break the logic within my while loop.
I've tried using a modification of "%*[^\n]\n" in my fscanf as:
while(fscanf(fp,"%d\t%f\t%f%*[^#]\n", &a[i], &b[i], &c[i]) != EOF)
but that causes a seg fault.
Config:
#hello and welcome to my config file
1666 -0.314913523 0.999804843 #blah blah
1667 -0.337279687 0.999865966
1703 -0.323162231 0.999774194
1704 -0.311984064 0.99964375
1705 -0.311984064 0.99964375
1706 -0.313381260 0.999671436
1707 -0.313170802 0.999558174
Code:
#include <iostream>
using namespace std;
#define NUM_ITEMS 50
int main()
{
FILE *fp;
fp = fopen("config.conf","r");
if(fp==NULL){
printf("No file.\n");
return -1;
}
int a[NUM_ITEMS];
float b[NUM_ITEMS];
float c[NUM_ITEMS];
int i = 0;
while(fscanf(fp,"%d\t%f\t%f", &a[i], &b[i], &c[i]) != EOF)
{
printf("-> %d %f %f\n", a[i], b[i], c[i]);
i++;
}
fclose(fp);
}
You can use fgets to read each line as a string and then check where '#' appears.
#include <stdio.h>
#define NUM_ITEMS 50
#define MAX_CHAR 500
ssize_t find_index(char *str)
{
size_t i=0U;
for (; *str!='\0'; i++)
{
if (*str++=='#')
{
return i;
}
}
return -1;
}
int main(void)
{
int a[NUM_ITEMS];
float b[NUM_ITEMS];
float c[NUM_ITEMS];
char buff[MAX_CHAR];
FILE *fp;
size_t i=0U;
ssize_t index=0U;
fp = fopen("config.conf","r");
if(!fp)
{
printf("No file.\n");
return -1;
}
while (fgets(buff,MAX_CHAR,fp))
{
index=find_index(buff);
if (index!=-1)
{
buff[index]='\0'; /* Bare in mind this will skip the newline character which fgets appends */
}
if(sscanf(buff,"%d%f%f", &a[i], &b[i], &c[i])==3) /* Checking scanf read 3 numbers */
{
printf("-> %d %f %f\n", a[i], b[i], c[i]);
i++;
}
}
return 0;
}
So find_index() returns the location of the element # was found. Then replaced by NULL terminator.
As Jonathan pointed out in the comments, you can also use the strcspn() function along with strlen() (for error checking) to find the index of #.
I'm trying to develop a function that reads each line of a text file and the it stores them in an array of strings (char**) but fgets() doesnt seem to work, it always return a null character.
Here is the function
char** getLines(FILE* fp){
char** lines;
int numberOfLines; //number of lines int the file
char ch; //aux var
int i; //counter
while(!feof(fp)){
ch = fgetc(fp);
if( ch == '\n'){
numberOfLines++;
}
}
lines = malloc(numberOfLines*sizeof(char*));
if (lines==NULL){
fprintf(stderr,"Error, malloc failed");
exit(1);
}
for(i = 0; i<numberOfLines; i++){
lines[i] = malloc(MAX_LENGTH*sizeof(char)); //MAX_LENGTH = 128
}
i=0;
while(fgets(lines[i], MAX_LENGTH,fp)){
printf("Line %d: %s \n",i,lines[i]);
i++;
}
return lines;
}
The function never gets inside the while loop so it doesn't print anything
I'm also using a very simple input file:
test line 1
test line 2
test line 3
test line 4
Hope you can help me,
Thank you in advance.
You are already on the end of the file before entering the while loop.
Take a look here http://en.cppreference.com/w/cpp/io/c/rewind
Moves the file position indicator to the beginning of the given file stream. The function is equivalent to std::fseek(stream, 0, SEEK_SET); except that end-of-file and error indicators are cleared. The function drops any effects from previous calls to ungetc.
Check if this works:
char** getLines(FILE* fp){
/* ...... */
i=0;
rewind(fp); // Rewind here
while(fgets(lines[i], MAX_LENGTH,fp)){
printf("Line %d: %s \n", i, lines[i]); // Also use the index as first parameter
i++;
}
return lines;
}
got some code here that won't compile correctly because it is saying that my pointer is already null when i am testing for a not null expression in my main function. here is the code :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXCODE 53
#define MAXMESSAGE 256
void getCode(char *codeIn, char *filename) {
FILE *codeFile;
/* Open the file with the code */
codeFile = fopen(filename, "r");
if (codeFile == NULL) {
printf("Error opening the code file - program terminated\n");
exit(1);
}
/* Read the first (and assumed only) line from the file */
fgets(codeIn, MAXCODE, codeFile);
/* Terminate the string with /0 */
codeIn[MAXCODE] = '\0';
/* Close the file */
fclose(codeFile);
return;
}
int getMessage(int *message, char *filename) {
FILE *messageFile;
int counter = 0;
/* Open the file with the message */
messageFile = fopen(filename, "r");
if (messageFile == NULL) {
printf("Error opening the message file - program terminated\n");
exit(1);
}
/* Read one number at a time from the file and store it */
while (!feof (messageFile))
{
fscanf (messageFile, "%d", (message+counter));
counter++;
}
/* Close the file */
fclose(messageFile);
return (counter);
}
void sortMessage(int *message, int size) {
int i, j, temp;
for (i=0; i<size-1; i++) {
for (j=i; j<size; j++) {
if (message[i]>message[j]) {
temp = message[i];
message[i] = message[j];
message[j] = temp;
}
}
}
return;
}
void decodeMessage(char *codeIn, int *message, int size) {
FILE *outputFile;
int i = 0;
/* Open the output file */
outputFile = fopen("csis.txt", "w");
if (outputFile == NULL) {
printf("Error opening the output file - program terminated\n");
exit(1);
}
for (i=0; i< size; i++) {
fprintf(outputFile, "%c", codeIn[message[i]%100]);
printf("%c", codeIn[message[i]%100]);
}
printf("\n");
/* Close the file */
fclose(outputFile);
return;
}
int main(int argc, char *argv[])
{
char code[MAXCODE];
int msg[MAXMESSAGE];
int msgSize;
if (argc != 3) {
printf("This program takes two arguments: the name of the file with the code, and the name of the file with the encoded message\n");
}
getCode(code, argv[1]);
msgSize = getMessage(msg, argv[2]);
sortMessage(msg, msgSize);
decodeMessage(code, msg, msgSize);
return;
}
So basically my code is using two files called codefile.txt and msgfile.txt to decode the secret message and write the decoded sequence to a new text file called csis.
As woolstar pointed out in the comments, you don't need to NUL terminate your codeIn array following fgets, because fgets will do that for you. In fact, this constitutes an overflow which we can best see by considering what happens when MAXCODE is 1: codeIn contains only one element: codeIn[0], and accessing codeIn[1] is an error.
Similarly, since MAXCODE is 53 and that's how many elements pointed to by codeIn, codeIn[message[i]%100] is suspicious because there's a potential for message[i]%100 to be an invalid index. While we're on this note, it might be wise to make message[i] an unsigned int so that it can't be negative. The format specifier (for printf and scanf) corresponding to unsigned int is %u.
while ( !feof(messageFile) ) is wrong because the EOF flag isn't set until an attempt is made at reading. Between attempting to read and your EOF test, however, you've incremented counter which means you've counted one too many items. Perhaps your loop should look like this:
while (fscanf(messageFile, "%d", (message+counter)) == 1)
{
counter++;
}
Note that this code assumes you've chosen to keep message[i] as an int. If you've chosen to use unsigned int instead, of course you'll want to use the %u format specifier.
You can probably see that feof is mostly superfluous... You can usually test for erroneous reads by checking the return value. Try to avoid feof in the future.
Your main function has a return type of int, yet at the end of it you have a return; statement which doesn't return an int value. Remove that. It's probably causing errors during compilation.
Presumably, when argv != 3 you want to return from main so you don't end up processing invalid arguments... Make sure you return an int value, e.g.
if (argc != 3) {
printf("This program takes two arguments: the name of the file with the code, and the name of the file with the encoded message\n");
return 0;
}
I need to read in a file that contains text, and then a double for that text. It is simply to get the mean and standard deviation for the set of numbers, so the text that comes before is irrelevant. For example, my input file looks a little like:
preface 7.0000
chapter_1 9.0000
chapter_2 12.0000
chapter_3 10.0000
etc..
In this case, it is finding the mean and std dev for the chapters of a book. I have the section of code below, but I'm not quite sure how to "ignore" the text, and only grab the doubles. At the moment this code prints out zeros and only exits the loop when it exceeds the array limit, which I set as a constant to 20 at the beginning of the program.
FILE *ifp;
char *mode = "r";
ifp = fopen("table.txt", mode);
double values[array_limit];
int i;
double sample;
if (ifp==NULL)
{
printf("cannot read file \n");
}
else
{
i = 0;
do
{
fscanf(ifp, "%lf", &sample);
if (!feof(ifp))
{
values[i] = sample;
printf("%.4lf \n", values[i]);
i++;
if (i>=array_limit) //prevents program from trying read past array size limit//
{
printf("No more space\n");
break;
}
}
else
{
printf("read complete\n");
printf("lines = %d\n", i);
}
}while (!feof(ifp));
fclose(ifp);
}
I think you could use fscanf(ifp, "%*[^ ] %lf", &sample) for reading from your file. The * says to ignore that particular match, the [] specifices a list of characters to match and the ^ indicates to match all characters except those in [].
Or possibly (a bit simpler) fscanf(ifp, "%*s %lf", &sample).
You have two major problems -- you're using feof which is pretty much always wrong, and you're not checking the return value of fscanf, which it what tells you whether you got a value or not (or whether you got to the eof).
So what you want is something like
while ((found = fscanf(ifp, "%lf", &values[i])) != EOF) { /* loop until eof */
if (found) {
/* got a value, so count it */
if (++i >= ARRAY_LIMIT) {
printf("no more space\n");
break;
}
} else {
/* something other than a value on input, so skip over it */
fscanf(ifp, "%*c%*[^-+.0-9]");
}
}
When reading in from a file, it's often best to use fgets to read one line at a time, then extract the parts you are interested in using sscanf:
#include <stdlib.h>
#include <stdio.h>
#define ARRAY_LIMIT 10
#define LINE_LENGTH 128
int main()
{
double values[ARRAY_LIMIT];
int i, count = 0;
double sample;
FILE *ifp = fopen("table.txt", "r");
if (ifp==NULL)
{
printf("cannot read file \n");
return 1;
}
char buff[LINE_LENGTH];
while (fgets(buff, LINE_LENGTH, ifp) != NULL)
{
if (sscanf(buff, "%*s %lf", &sample) != 1) break;
values[count++] = sample;
if (count == ARRAY_LIMIT) {
printf("No more space\n");
break;
}
}
fclose(ifp);
for (i = 0; i < count; ++i) {
printf("%d: %f\n", i, values[i]);
}
return 0;
}
fgets returns NULL if it encounters the end of the file, or if a read error has occurred. Otherwise, it reads one line of the file into the character buffer buff.
The asterisk %*s in the sscanf means that the first part of the line is discarded. The second part is written to the variable sample. I am checking the return value of sscanf, which indicates how many values have been read successfully.
The loop breaks when the end of the file is reached or the count reaches the size of the array.
The code is supposed to read a user-inputted text file name, copy every character into a multidimensional array, then display it with standard output. It compiles, but produces unintelligible text. Am I missing something?
for (i = 0; i < BIGGEST; i++) {
for (j = 0; j < BIGGESTL; j++) {
if (fgetc(array, fp) ) != EOF)
array[i][j] = c;
else array[i][j] = '\0'
}
fclose(fp);
return 0;
}
You stop filling the array when you encounter EOF, but you print the full array out no matter what.
If the data read from the file is smaller than the input array, you will read that data in and then print that data out, plus whatever random characters were in the memory locations that you do not overwrite with data from the file.
Since the requirement seems to be to print text data, you could insert a special marker in the array (e.g. '\0') to indicate the position where you encountered EOF, and stop displaying data when you reach that marker.
You had better read each line from file
For example:
int i = 0;
while(fgets(text[i],1000,fp))
{
i++;
}
Though the question is edited and only part of the code is left in question. I am posting more than what is required for the question at the moment.
Reason being, there can be numberous improvements to originally posted full code.
In main() function:
You need to check for the argc value to be equal to 2 for your purpose and only then read in value of argv[1] . Else if program executed without the command-line-argument which is file_name in this case, invalid memory read occurs, resulting in segmentation fault if you read in argv[1].
In read_file_and_show_the contents() function:
Stop reading file if end of file is reached or maximum characters is read and store in the character array.
Below Program will help you visualize:
#include <stdio.h>
/*Max number of characters to be read/write from file*/
#define MAX_CHAR_FOR_FILE_OPERATION 1000000
int read_and_show_the_file(char *filename)
{
FILE *fp;
char text[MAX_CHAR_FOR_FILE_OPERATION];
int i;
fp = fopen(filename, "r");
if(fp == NULL)
{
printf("File Pointer is invalid\n");
return -1;
}
//Ensure array write starts from beginning
i = 0;
//Read over file contents until either EOF is reached or maximum characters is read and store in character array
while( (fgets(&text[i++],sizeof(char)+1,fp) != NULL) && (i<MAX_CHAR_FOR_FILE_OPERATION) ) ;
//Ensure array read starts from beginning
i = 0;
while((text[i] != '\0') && (i<MAX_CHAR_FOR_FILE_OPERATION) )
{
printf("%c",text[i++]);
}
fclose(fp);
return 0;
}
int main(int argc, char *argv[])
{
if(argc != 2)
{
printf("Execute the program along with file name to be read and printed. \n\
\rFormat : \"%s <file-name>\"\n",argv[0]);
return -1;
}
char *filename = argv[1];
if( (read_and_show_the_file(filename)) == 0)
{
printf("File Read and Print to stdout is successful\n");
}
return 0;
}