Why do I get weird number after reading from file? - c

I get weird values after reading from file (i should be max 100 but I get more), and if someone would explain when to use & * ** in pointers in a simple why couse my english is not very good when it comes to programing I would be grateful
This program should read words from file and if there is a number in the word change it to first letter of that word. If you have any suggestions on how I could change file reading I would also appreciate that. I am new to C (in school I did C++ but very basic levels)
# include <stdio.h>
# define MAX_LEN 100
int File_reading();
int main()
{char buffer;
File_reading();
}
int File_reading( )
{
FILE *stream;
char buffer[MAX_LEN + 1];
int i, ch;
stream = fopen("data.txt","r");
for (i = 0; (i < (MAX_LEN+1));i++)
{
if (((ch = fgetc(stream)) != EOF) && (ch != '\n'))
{
buffer[i] = ch;
}
}
buffer[i] = '\0';
if (fclose(stream))
perror("fclose error");
for (i=0;(i<(MAX_LEN+1));i++){
printf("%c \n", buffer[i]);
}
}

You're not stopping the loop when the file is over, and you're overstepping the array bound! That's terrible. Fix the loop, like this:
char buffer[MAX_LEN + 1];
size_t i;
for (i = 0; i != MAX_LEN; ++i)
{
int c = fgetc(stream);
if (c == EOF) { break; }
buffer[i] = c;
}
buffer[i] = '\0';

Related

My program can't output the lines correctly

I'm relatively new in C and I currently reading Kernighan's book.
One of the problems in the book is to create an algorithm that from a input line output the line if it is more than 10 characters long.
The point is I'm frustrated because I cant find what is wrong with my code. I debugged and recreate it many times but still cant find out what's going on!
The escape character from function getl() is '.' (dot), and sometimes works and other times don't. If you compile it and test you will see:
gcc -Wall -o out 'script.c'
The question header from the book is:
“Exercise 1-17. Write a program to print all input lines that are longer than 10 characters.”
I'm sure that's relatively easy, but I really wanted to know why this algorithm is not working as expected, i think it has something to do with '\n'.
If someone could help me find out what's the problem with the code, I would appreciate it.
Code
#include <stdio.h>
#define MAX 10000
int getl(char line[], int lim) {
char c;
int count;
for (count = 0 ; count < lim-1 && (c = getchar()) != '.' ; count++) {
if (c == '\n') {
line[count] = '\n';
count++;
break;
}
line[count] = c;
}
line[count] = '\0';
return count;
}
int main() {
char line[MAX];
int len = 1;
for (; len > 0 ;) {
getl(line, MAX);
len = getl(line, MAX);
if (len >= 10)
printf("%s", line);
}
return 0;
}
Your code almost works. You just seem to have some repeated lines here and there that confuse things.
Specifically, you are calling getl(line, MAX); twice in a row. The first gets the input, but don't save the count, the second has only an empty stdin buffer to work with so no sensible count is saved from that. Removing the first call that don't save the count fixes your issue.
#include <stdio.h>
#define MAX 10000
int getl(char line[], int lim) {
char c = getchar();
int count;
for (count = 0 ; c != '.' ; count++) {
line[count] = c;
c = getchar();
}
line[count++] = '\n';
return count;
}
int main() {
char line[MAX];
int len = 1;
for (; len > 0 ;) {
len = getl(line, MAX);
if (len >= 10)
printf("%s", line);
}
return 0;
}
First, you're calling your getl function twice instead of once (you only want to read lines one by one). Fixing that should work.
Then I think you shouldn't add the trailing '\n' to your lines, just print it when your line is longer than 10 characters, in your code, the '\n' will be counted as a character.
Here's the modified code:
#include <stdlib.h>
#include <stdio.h>
#define MAX 10000
int getl(char line[])
{
char c;
int count;
for (count = 0; count < MAX - 1 && (c = getchar()) != '.' ; count++)
{
if (c == '\n')
break;
line[count] = c;
}
line[count] = '\0';
return (count);
}
int main()
{
char line[MAX];
int len = 1;
while (len > 0)
{
len = getl(line);
if (len >= 10)
printf("%s, c = %i\n", line, len);
}
return (0);
}
This should work. https://ideone.com/cXXRUH
#include <stdio.h>
#define MAX 10000
int getline_length(char line[]) {
char ch;
int count = 0;
printf("\nWaiting for INPUT...");
// Using clear while loop to get input, removing redundent complexity
// Either `.` or `\n` consider End Of Line
while(count < MAX-1 && ((ch = getchar()) != '.' || (ch = getchar()) != '\n')) {
line[count++]=ch;
}
line[count] = '\0';
return count;
}
int main() {
char line[MAX];
while(1) {
// reset array before each input
memset(line, 0, sizeof(line));
int len = getline_length(line); //No need to pass limit
if (len >= 10) {
printf("%s", line);
} else {
printf("len < 10");
}
}
return 0;
}

Get length of char array with null elements in C

Currently I am making a project that uses char arrays that have null elements. I want to be able to get the length of the array, in the sense of the number of elements that aren't null. This seemed reasonably trivial and I made this function:
int getWordLen(char word[]) {
int count = 0;
for (int i = 0; i < 512; i++) {
if (word[i] != '\0') {
count++;
}
}
printf("%d ", count);
return count;
}
However, every char array returns a length of 188. Any help would be appreciated.
This is the function I was calling it from:
void redact(Words * redactWords, char fileName[]) {
FILE * file = fopen(fileName, "r");
FILE * outputFile = fopen("outputFile.txt", "w+");
char word[512];
int i = 0;
char c;
while (c != EOF) {
c = getc(file);
if ((c > 96) && (c < 123)) {
word[i] = c;
i++;
continue;
}
else if ((c > 64) && (c < 91)) {
word[i] = c + 32;
i++;
continue;
}
i = 0;
if (isWordRedactWord(redactWords, word)) {
//write stars to file
char starStr[512];
for (int i = 0; i < getWordLen(word); i++) {
starStr[i] = '*';
}
fputs(starStr, outputFile);
}
else {
//write word to file
fputs(word, outputFile);
}
strcpy(word, emptyWord(word));
}
fclose(file);
fclose(outputFile);
}
In the initial while, I would only use while(!EOF).
Also, I believe you are using a lot more resources than necessary with the implementation of that for inside the while:
char starStr[512];
for (int i = 0; i < getWordLen(word); i++) {
starStr[i] = '*';
I suggest you to put it outside the while loop and see what happens.
If it is always giving you 188 of lenght, it is counting something that's constant, and may be related to that outer loop.
Hope you can solve it!

Replacing three 'a' in with a single '*' in a string

So my program should get input from an user and store it in an array. After that if the input string includes three 'a's in a row it should be replaced with a single '*'. However I can't seem to get it right. It only replaces the first a with a *. I tried to replace the following 2 a with a blank but the output looks funny.
For this exercise I have to use putchar() and getchar().
Thank you in advance.
#include <stdio.h>
char c;
char buffer[256];
int counter= 0;
int i;
int main()
{
while ((c = getchar()) != '\n') {
buffer[counter] =c;
counter++;
if (counter >255) {
break;
}
}
for(i=0; i<256; i++) {
if(buffer[i]== 'a'&&buffer[i+1]=='a'&&buffer[i+2]=='a')
{
buffer[i]= '*';
buffer[i+1]=' ';
buffer[i+2]=' ';
}
putchar(buffer[i]);
}
putchar('\n');
return 0;
}
So my program should get input from an user and store it in an array.
After that if the input string includes three 'a's in a row it should
be replaced with a single '*'. However I can't seem to get it right.
You almost got it! Just move index by 2 to and continue.
#include <stdio.h>
char c;
char buffer[256];
int counter= 0;
int i;
int main(void)
{
while ((c = getchar()) != '\n') {
buffer[counter] =c;
counter++;
if (counter >= 255) {
break;
}
}
buffer[counter] ='\0';
for(i=0; i<256; i++) {
if(buffer[i]== 'a'&&buffer[i+1]=='a'&&buffer[i+2]=='a')
{
buffer[i]= '*';
putchar(buffer[i]);
i = i + 2;
continue;
}
putchar(buffer[i]);
}
putchar('\n');
return 0;
}
Test:
123aaa456aaa78
123*456*78
In string you must assign a end of character at the end and that is call null character \0 or just a numeric 0. Correct your code like below:-
while ((c = getchar()) != '\n') {
buffer[counter] =c;
counter++;
if (counter >=255) {
break;
}
}
buffer[counter] ='\0';// or buffer[counter] =0;
To avoid side effect in a string array always set all its value with 0 first:-
char buffer[256];
memset(buffer, 0, sizeof(buffer));
If you want to change the number of characters, you will need to create a different buffer to copy the output to.
If you really just want to output to the console, you could just write every character until you hit your matching string.
#include <stdio.h>
char c;
char buffer[256];
char output[256];
int counter= 0;
int i, j;
int main()
{
while ((c = getchar()) != '\n') {
buffer[counter] = c;
counter++;
if (counter >255) {
break;
}
}
buffer[counter] = 0;
for(i=0, j=0; i<256; i++, j++) {
if(buffer[i] == 'a' && buffer[i+1] == 'a'&& buffer[i+2] == 'a')
{
output[j]= '*';
i += 2;
}
else
output[j] = buffer[i];
putchar(output[j]);
}
putchar('\n');
return 0;
}
There are multiple problems in your code:
there is no reason to make all these variables global. Declare them locally in the body of the main function.
use int for the type of c as the return value of getchar() does not fit in a char.
you do not check for EOF.
your test for buffer overflow is off by one.
you do not null terminate the string in buffer. You probably make buffer global so it is initialized to all bits 0, but a better solution is to set the null terminator explicitly after the reading loop.
to replace a sequence of 3 characters with a single one, you need to copy the rest of the string.
You can use a simple method referred as the 2 finger approach: you use 2 different index variables into the same array, one for reading, one for writing.
Here is how it works:
#include <stdio.h>
int main() {
char buffer[256];
int c;
size_t i, j, counter;
for (counter = 0; counter < sizeof(buffer) - 1; counter++) {
if ((c = getchar()) == EOF || c == '\n')
break;
buffer[counter] = c;
}
buffer[counter] = '\0';
for (i = j = 0; i < counter; i++, j++) {
if (buffer[i] == 'a' && buffer[i + 1] == 'a' && buffer[i + 2] == 'a') {
buffer[j] = '*';
i += 2;
} else {
buffer[j] = buffer[i];
}
}
buffer[j] = '\0'; /* set the null terminator, the string may be shorter */
printf("modified string: %s\n", buffer);
return 0;
}

Segmentation fault when appending char to string in string array

So I want to get all the lines from a file and turn them into a char* array. Problem is that whenever I try to append the character onto the end of the element it gives a segmentation fault.
char** loadOutputs(char *fileName, int *lineCount)
{
FILE *file = fopen(fileName, "r");
if (file) {
char c;
int lines = 0;
while ((c = fgetc(file)) != EOF)
if (c = '\n')
lines++;
rewind(file);
char **output = malloc(lines * sizeof(char*));
for (int i = 0; i < lines; i++)
output[i] = "";
int index = 0;
while ((c = fgetc(file)) != EOF)
if (c == '\n')
index++;
else
strcat(output[i], &c);
return output;
}
return NULL;
}
I always get a segmentation fault at strcat(output[i], &c);. I'd rather not create a fixed array size for the output because this could get fairly large and I don't want to use too much memory.
The following code:
for (int i = 0; i < lines; i++)
output[i] = "";
Is setting the pointer to an empty read only string.
You need to allocate some memory for the string:
I.e.
for (int i = 0; i < lines; i++) {
output[i] = malloc(MAX_LINE_LENGTH + 1);
}
Where MAX_LINE_LENGTH is some defined constant - perhaps #define MAX_LINE_LENGTH 100.
You will need to check that when reading the lines you do not exceed this length.
The following code will do this. This will resolve the other problem in that the address of c will not point to a null terminated string.
int index = 0;
int position = 0;
while ((c = fgetc(file)) != EOF) {
if (c == '\n') {
output[index][position] = 0; // Null terminate the line
position = 0; // Restart next line
index++;
} else {
if (position < MAX_LINE_LENGTH) { // Check if we have space!
output[index][position] = c; // Add character and move forward
position++;
}
}
}
output[index][position] = 0; // Add the null to the final line
Also you need to declare c as and int - i.e. change char c to int c. This is because EOF is outside the range for a char

How do I get proper output from fgets when called from a separate thread?

I would like to read a file line by line in a thread that I have created, but for some reason, the result that I'm getting from fgets is just garbage. What is the cause of this problem and how would I go about fixing it?
Here is the problem area, which is contained in its own thread:
FILE *orders = fopen("orders.txt","r");
int numOrders;
numOrders = getNumLines(orders);
int orderLineSize = getMaxLineCount(orders);
char Line[orderLineSize];
fgets(Line,orderLineSize,orders); // This is the call that gives me a garbage output
printf("Line is: %s\n",Line);
This is what is contained in Line: ;3+. However, this changes every time I run the program
And this is what orders.txt contains:
"I Could Pee on This: And Other Poems by Cats"|7.49|1|HOUSING01
"Across Islands and Oceans"|1.99|1|SPORTS01
"Soul Surfer"|7.99|3|SPORTS01
"The Immortal Life of Henrietta Lacks"|8.91|4|POLITICS01
"The Handbuilt Home: 34 Simple Stylish and Budget-Friendly Woodworking Projects for Every Room"|15.63|1|HOUSING01
"The History of Surfing"|31.5|2|SPORTS01
Here is getMaxLineCount:
int getMaxLineCount(FILE *filePtr)
{
char c;
int lineCount;
int maxCount;
lineCount = 0;
maxCount = 0;
while(c != EOF)
{
c = fgetc(filePtr);
lineCount++;
if((c == '\n') && (lineCount > maxCount))
{
maxCount = lineCount;
lineCount = 0;
}
}
rewind(filePtr);
return maxCount;
}
getNumLines:
int getNumLines(FILE *filePtr)
{
char c;
int lineCount;
int maxCount;
lineCount = 0;
maxCount = 0;
int peopleCount;
peopleCount = 0;
while(c != EOF)
{
c = fgetc(filePtr);
if(c == '\n')
peopleCount++;
}
rewind(filePtr);
return peopleCount;
}
My guess is that getMaxLineCount is consuming the file, so you have to rewind it.
Before the call to fgets, try adding
rewind(orders);
Unless multiple threads are trying to read the same file, this issue should have nothing to do with threading.
Update: The following short program works fine for me.
Update2: I have fixed at least some of the undefined behavior mentioned by #chux.
Update3: by chux changed to size_t. Re-order to allow last line to be tested if longest. Move lineCount = 0; (it had only happened when a new max was found.)
#include <stdio.h>
#include <stdlib.h>
size_t getMaxLineCount(FILE *filePtr)
{
int c; // Changed `char` to int
size_t lineCount;
size_t maxCount;
lineCount = 0;
maxCount = 0;
while(1)
{
c = fgetc(filePtr);
if (c == EOF) break;
lineCount++;
if (c == '\n')
{
if (lineCount > maxCount) maxCount = lineCount;
lineCount = 0;
}
}
if (lineCount > maxCount) maxCount = lineCount;
rewind(filePtr);
return maxCount;
}
int main(){
FILE *orders = fopen("orders.txt","r");
size_t orderLineSize = getMaxLineCount(orders);
char Line[orderLineSize+1]; // Extra space for the buffer.
fgets(Line,orderLineSize,orders); // This works fine for me.
printf("Line is: %s\n",Line);
}

Resources