I am learning file handling in C. I wrote code to replace a line in a file with a string input by the user. The replacing progress itself works great, but somehow the first line is always empty and I am able to understand what goes wrong.
Additionally I have some additional questions about file handling itself and about tracking down the mistakes in my code. I understand by now that I should have used perror() and errno. This will be the next thing I will read on.
Why shouldn't I use "w+" establishing the file stream? (A user on here told me to better not use it, unfortunately I couldn't get an explanation)
I tried to use gdb to find the mistake, but when I display my fileStored array I get only numbers, since its obviously an int array, how could I improve the displaying of the variable
What would be a good approach in gdb to track the mistake down I made in the code?
The code:
#include <stdio.h>
#include <stdlib.h>
#define MAXLENGTH 100
int main(int argc, char *argv[]){
FILE *fileRead;
char fileName[MAXLENGTH],newLine[MAXLENGTH];
int fileStored[MAXLENGTH][MAXLENGTH];
short lineNumber, lines = 0;
int readChar;
printf("Input the filename to be opened:");
int i = 0;
while((fileName[i] = getchar()) != '\n' && fileName[i] != EOF && i < MAXLENGTH){
i++;
}
fileName[i] = '\0';
if((fileRead = fopen(fileName, "r")) == NULL){
printf("Error: File not found!\n");
return EXIT_FAILURE;
}
i = 0;
while((readChar = fgetc(fileRead)) != EOF){
if(readChar == '\n'){
fileStored[lines][i] = readChar;
i = 0;
lines++;
}
fileStored[lines][i] = readChar;
i++;
}
fclose(fileRead);
fileRead = fopen(fileName, "w");
printf("Input the content of the new line:");
i = 0;
while((newLine[i] = getchar()) != '\n' && newLine[i] != EOF && i < MAXLENGTH){
i++;
}
newLine[i] = '\0';
printf("There are %d lines.\nInput the line number you want to replace:",lines);
scanf("%d",&lineNumber);
if((lineNumber > lines) || (lineNumber <=0)){
printf("Error: Line does not exist!");
return EXIT_FAILURE;
}
int j = 0;
for(i = 0; i < lines; i++){
if(i == lineNumber-1){
fprintf(fileRead,"\n%s",newLine);
continue;
}
do{
fputc(fileStored[i][j],fileRead);
j++;
}while(fileStored[i][j] != '\n');
j = 0;
}
fclose(fileRead);
return EXIT_SUCCESS;
}
Related
Whenever I make ch[index]==0, it gives me first word from text file but whenever I select ch[index]==1, it gives me nothing. How to make this if statement working?
#include <stdio.h>
#include<stdlib.h>
int main(){
FILE * fr = fopen("/home/bilal/Documents/file.txt","r");
char ch[100];
int index = 0;
if(fr != NULL){
while((ch[index] = fgetc(fr)) != EOF){
if(index[ch]==1){ // here is if statement
if(ch[index] == ' ') {
ch[index] = '\0';
printf("Here is your %s: \n",ch);
index = 0;
}
else { index++; }
}
}
fclose(fr);
}
else{ printf("Unable to read file."); }
return 0;
}
For a start you have an fclose(fr) inside your i loop, but then you never open the file again. You are also incrementing i inside the loop a second time, which is never good in practice.
try this:
for (int i=0; i<8; i++){
fr = fopen("/home/bilal/Documents/file.txt","r");
index = 0;
if(fr != NULL){
and remove the fopen from the top.
There is probably a better way than opening and closing the file on each loop iteration.
Here is a code that should work and show the second word, although I didn't test it:
#include <stdio.h>
//#include <stdlib.h> //not needed
int main(void)
{
FILE* fr = fopen("/home/bilal/Documents/file.txt", "r");
char ch[100];
int index = 0, c, i = 0;
//for loop is useless
if (fr == NULL)
{
printf("Unable to read file.");
return 0;
//I prefer error checking without a giant if statement, but it's up to you
}
c = fgetc(fr); //fgetc() returns an int, not char
while (c != EOF)
{
ch[index] = c;
if (ch[index] == ' ')
{
if (i == 1)
{
ch[index] = '\0';
printf("Here is your string: %s\n", ch); //The format seemed weird to me, that's why I changed it, use what you need
}
index = 0;
i++;
}
else
index++;
c = fgetc(fr);
}
fclose(fr);
//return 0; //not needed in C99 or later
}
I'm trying to read a file that contains 10 numbers then adding them to an array so I can sort them later on but I'm having trouble reading them in. Not sure why this isn't working for me, can someone explain what is wrong? There's only a number on each lines.
10.05
11.01
9.03
double nums[10] = {0};
int count;
if ((fptr = fopen("filename", "r")) == NULL){
printf("Error opening file.\n");
}
while ((c = getc(fptr)) != EOF){
if (c != '\n'){
nums[count] = (double)c;
count = count + 1;
}
}
fclose(fptr);
What is wrong:
You are storing only one character.
You are updating count each times on non-newline characters while updating should be on newline characters.
count is used without being initialized.
Casting to double is not for this usage.
Possible fix:
int c;
FILE* fptr;
char line[1024]; // add line buffer and size tracking
int lineCount = 0;
double nums[10] = {0};
int count = 0; // initialize count
if ((fptr = fopen("filename", "r")) == NULL){
printf("Error opening file.\n");
} else { // avoid using NULL to read file
while ((c = getc(fptr)) != EOF){
if (c == '\n'){ // update nums on newline character
line[lineCount] = '\0'; // don't forget to terminate the string
nums[count] = atof(line); // atof() from stdlib.h is useful to convert string to number
count = count + 1;
lineCount = 0; // start to read next line
} else { // read line contents
line[lineCount] = (char)c;
lineCount = lineCount + 1;
}
}
fclose(fptr);
}
Here I go
#include <stdio.h>
#include <stdlib.h>
int main()
{
double values[10];
int count;
FILE *f = fopen("filename", "r");
if (f == NULL)| {
fprintf(stderr, "Some error message");
return EXIT_FAILURE; // We cannot go any further - file is dead
}
// This is basic - you could overcome error problems
// When able to read (including white space) we carry on until the array is full
// This is an area for improvement - error checking etc.
for (count = 0; count < 10 && fscanf(f, " %lf", &values[count]) != 1; count ++);
fclose(f);
return EXIT_SUCCESS;
}
I gotta write a file-handing code which will compare the string received from the user to a string of char stored into a file in C. I've trying since yesterday. I have no clue on how to do that. I tried many things, but nothing seems to work.
//
// 2.c
// IFTM Exercises
//
// Created by Lelre Ferreira on 10/27/19.
// Copyright © 2019 Lelre Ferreira. All rights reserved.
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (int argc, const char * argv[]){
FILE *file = fopen("file.txt", "w");
char text[] = "hi hi hi hi hi hi"; //string to be allocated into the file
char c, userInput[] = "hi"; // simulates the user input
int i = 0, count = 0;
if (file == NULL) {
printf("Failure to create file.\n");
exit(1);
} else {
for (i = 0; i < strlen(text); i++) {
printf("Inserting: [%c]\n", text[i]);
fputc(text[i], file);
}
printf("All done.\n");
}
fclose(file);
fopen("file.txt", "r");
while ((c = fgetc(file) != EOF)){
fscanf(file, "%s", text);
if (strcmp(userInput, text) == 0) {
count++;
}
}
fclose(file);
printf("Many times present: %d\n", count);
return 0;
}
My problem is... the space between every word of the string in the file, because I have to check if there's another word starting, for instance... (Hi Hi)... I thought about using something like this in my code but I did not work as well.
while ((c = fgetc(file) != EOF)){ // While the end of the file does not happen keep running.
if ((c = fgetc(file) != ' ')) { //If an blank space is found... I does not make any sense actually. I'm desesperated.
strcmp(userInput, text){
count++
}
}
}
while ((c = fgetc(file) != EOF)){
if ((c = fgetc(file) != ' ')) {
strcmp(userInput, text){
count++
}
}
}
There are three major problems here.
First, c = fgetc(file) != EOF is the same as c = (fgetc(file) != EOF) which obviously is not what you want. It should be (c = fgetc(file)) != EOF
Second, the above statement has (provided you did not get an EOF) actually read a character. So the if statement should be if(c != ' ')
Third, c needs to be declared as an int
I am trying to solve a C Program problem:
Create a program in C that reads a string from a text file and then reorders the string in an odd-even format (first take odd numbered letters and then even numbered letters; example: if the program reads elephant, then the reordered string will be eehnlpat). Then write the string in a different text file. Provide an error-checking mechanism for both reading and writing.
My code is:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
FILE *inputFile;
inputFile = fopen("inpFile.txt", "r");
if (inputFile != NULL) {
FILE *outFile = fopen("outFile.txt", "w");
if (outFile != NULL) {
printf("file created successfully\n");
int i, j = 0;
char strf1[50];
fscanf(inputFile, "%s", &strf1);
char strf2[strlen(strf1)];
for (i = 0; strf1[i] > 0; i++) {
if (i % 2 == 0) {
strf2[j] = strf1[i];
j++;
}
}
for (i = 1; strf1[i] > 0; i++) {
if (i % 2 == 1) {
strf2[j] = strf1[i];
j++;
}
}
fprintf(outFile, "%s\n", strf2);
fclose(outFile);
} else {
printf("file could not be created\n");
}
fclose(inputFile);
} else {
printf("File does not exist.");
}
return 0;
}
I feel all is OK but the problem is if the program reads elephant, then the reordered string given by my program is eehnlpatZ0#. Where extra Z0# is my problem. I don't want that extra thing. But I can't fix it. If anybody can help me to fix it, that will be great.
Your target string is too short: char strf2[strlen(strf1)];. You should at least allow for a null terminator and set it, or simply make the output array the same size as the input array:
char strf2[50];
There are other problems in your code:
In case of error by fopen, it would be advisable to return a non-zero status to the system.
You should pass the array to fscanf(), not a pointer to the array, which has a different type.
You should tell fscanf() the maximum number of characters to read into the array with %49s
You should test the return value of fscanf() and produce an empty output file for an empty input file. The current code has undefined behavior in this case.
The test strf1[i] > 0 is incorrect: characters from the input file might be negative. You should either compute the string length or test with strf1[i] != '\0'
Starting the second loop at i = 1 seems a good idea, but it relies on the silent assumption that strf1 is not an empty string. In your example, if fscanf() succeeds, strf1 is not empty, and if it fails the behavior is undefined because strf1 is uninitialized. Yet it is safer to avoid such optimisations which will bite you if you later move the code to a generic function for which the assumption might not hold.
You must null terminate the output string before passing it to fprintf or specify the length with a %.*s format.
Here is a corrected version:
#include <stdio.h>
int main() {
FILE *inputFile, *outFile;
char strf1[50], strf2[50];
int i, j;
inputFile = fopen("inpFile.txt", "r");
if (inputFile == NULL) {
printf("Cannot open input file inpFile.txt\n");
return 1;
}
outFile = fopen("outFile.txt", "w");
if (outFile == NULL) {
printf("Could not create output file outFile.txt\n");
fclose(inputFile);
return 1;
}
printf("file created successfully\n");
if (fscanf(inputFile, "%49s", strf1) == 1) {
j = 0;
for (i = 0; strf1[i] != '\0'; i++) {
if (i % 2 == 0)
strf2[j++] = strf1[i];
}
for (i = 0; strf1[i] != '\0'; i++) {
if (i % 2 == 1)
strf2[j++] = strf1[i];
}
strf2[j] = '\0';
fprintf(outFile, "%s\n", strf2);
}
fclose(inputFile);
fclose(outFile);
return 0;
}
Here is an alternative with simpler copy loops:
int len = strlen(strf1);
j = 0;
for (i = 0; i < len; i += 2) {
strf2[j++] = strf1[i];
}
for (i = 1; i < len; i += 2) {
strf2[j++] = strf1[i];
}
strf2[j] = '\0';
You have to provide a space for the null-terminator, since you did not provide a space for it, printf cannot know when your string is terminated, so it contiues to print out data from the memory.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
FILE* inputFile;
inputFile=fopen("inpFile.txt", "r");
if (inputFile!=NULL) {
FILE* outFile=fopen("outFile.txt", "w");
if (outFile!=NULL) {
printf("file created successfully\n");
int i, j=0;
char strf1[50];
fscanf(inputFile, "%s",&strf1);
int inputLength = strlen(strf1) + 1;
char strf2[inputLength];
char strf2[inputLength-1] = '\0';
for(i=0; strf1[i]>0; i++) {
if(i%2==0) {
strf2[j]=strf1[i];
j++;
}
}
for(i=1; strf1[i]>0; i++) {
if(i%2==1) {
strf2[j]=strf1[i];
j++;
}
}
fprintf(outFile, "%s\n",strf2);
fclose(outFile);
}else{
printf("file could not be created\n");
}
fclose(inputFile);
}
else {
printf("File does not exist.");
}
return 0;
}
In C, strings require a Null character, '\0', as the last byte in order to terminate.
Changing the following line of code from
char strf2[strlen(strf1)];
to
char strf2[strlen(strf1) + 1];
will solve this problem.
So what I'm trying to do is to count blank lines, which means not only just containing '\n'but space and tab symbols as well. Any help is appreciated! :)
char line[300];
int emptyline = 0;
FILE *fp;
fp = fopen("test.txt", "r");
if(fp == NULL)
{
perror("Error while opening the file. \n");
system("pause");
}
else
{
while (fgets(line, sizeof line, fp))
{
int i = 0;
if (line[i] != '\n' && line[i] != '\t' && line[i] != ' ')
{
i++;
}
emptyline++;
}
printf("\n The number of empty lines is: %d\n", emptyline);
}
fclose(fp);
You should try and get your code right when posting on SO. You are incrementing both i and emptyline but the use el in your call to printf(). And then I don't know what that is supposed to be in your code where it has }ine. Please, at least make an effort.
For starters, you are incrementing emptyline for every line because it is outside of your if statement.
Second, you need to test the entire line to see if it contains any character that is not a whitespace character. Only if that is true should you increment emptyline.
int IsEmptyLine(char *line)
{
while (*line)
{
if (!isspace(*line++))
return 0;
}
return 1;
}
Before getting into the line loop increment the emptyLine counter and if an non whitespace character is encountred decrement the emptyLine counter then break the loop.
#include <stdio.h>
#include <string.h>
int getEmptyLines(const char *fileName)
{
char line[300];
int emptyLine = 0;
FILE *fp = fopen("text.txt", "r");
if (fp == NULL) {
printf("Error: Could not open specified file!\n");
return -1;
}
else {
while(fgets(line, 300, fp)) {
int i = 0;
int len = strlen(line);
emptyLine++;
for (i = 0; i < len; i++) {
if (line[i] != '\n' && line[i] != '\t' && line[i] != ' ') {
emptyLine--;
break;
}
}
}
return emptyLine;
}
}
int main(void)
{
const char fileName[] = "text.txt";
int emptyLines = getEmptyLines(fileName);
if (emptyLines >= 0) {
printf("The number of empty lines is %d", emptyLines);
}
return 0;
}
You are incrementing emptyline on every iteration, so you should wrap it in an else block.
Let's think of this problem logically, and let's use functions to make it clear what is going on.
First, we want to detect lines that only consist of whitespace. So let's create a function to do that.
bool StringIsOnlyWhitespace(const char * line) {
int i;
for (i=0; line[i] != '\0'; ++i)
if (!isspace(line[i]))
return false;
return true;
}
Now that we have a test function, let's build a loop around it.
while (fgets(line, sizeof line, fp)) {
if (StringIsOnlyWhitespace(line))
emptyline++;
}
printf("\n The number of empty lines is: %d\n", emptyline);
Note that fgets() will not return a full line (just part of it) on lines that have at least sizeof(line) characters.