Getting garbage value at the end of some strings - c

I scraped a website to get some mcqs for a c assignment. I wrote the data to a plaintext file separating every entry with null chars.
The pattern is:
Question with choices NULL Answer NULL Question...
Here is a sample of the file. the red dots are '\0' chars:
Here is a link to get the full file.
Code to read this file in C:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Question{
char question[1000];
char answer;
};
int main(){
struct Question questions[100];
FILE *fp;
char buffer[1000],choice;
int ch,i=0,c=1,k=0,score=0;
fp=fopen("quiz_questions.txt","r");
ch = 1;
while (ch != EOF)
{
ch = getc(fp);
buffer[i]=ch;
i++;
if(ch=='\0'){
buffer[i]='\0';
c++;
i=0;
continue;
}
if(c%2){ //question
strcpy(questions[k].question,buffer);
}
else{ //answer
questions[k].answer=buffer[0];
k++;
}
}
for(i=0;i<35;i++){
printf("\nQuestion:\n%s\nAnswer: %c\n",questions[i].question,questions[i].answer);
}
return 0;
}
OUTPUT:
What am I missing? Help please. It seems the buffer isn't getting null terminated properly and is retaining chars from last assignment.
PS: Is there a better way to consume this data from c? Scraping done via python.
EDIT: I now realize writing a separate answerkey file would have been much better. Stupid me.

strcpy(questions[k].question,buffer);
This statement is executed for every single character you read (if c is odd). At this point, buffer is not null terminated yet (and not a string).
ch = getc(fp);
buffer[i]=ch;
These two lines write to buffer[i] even if the end of file was reached. You only check for EOF after having processed it as if it were a normal character.
i++;
if(ch=='\0'){
buffer[i]='\0';
This is redundant. If ch is '\0', then you've just null terminated buffer in buffer[i]=ch;. There's no need to add another '\0'.

Modified version of your code to solve the problem:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Question{
char question[1000];
char answer;
};
int main()
{
struct Question questions[100];
FILE *fp;
char buffer[1000],choice;
int ch,i=0,c=0,k=0,score=0; **<-- EDIT:change done here to initialize c = 0**
fp=fopen("quiz_questions.txt","r");
ch = 1;
while (ch != EOF)
{
ch = getc(fp);
buffer[i]=ch;
i++;
if(ch =='\0')
{
//buffer[i]='\0'; <-- Change done here, unnecessary assignment
c++;
i=0;
if(c%2) <-- Change done here, moved inside if (ch == '\0') case
{
//question
strcpy(questions[k].question,buffer);
}
else
{
//answer
questions[k].answer=buffer[0];
k++;
}
}
}
for(i=0;i<35;i++)
{
printf("\nQuestion:\n%s\nAnswer: %c\n",questions[i].question,questions[i].answer);
}
return 0;
}

Related

How do I store repeated null characters in a string in C from fgetc?

EDIT: This simply doesn't work reliably with strings. I have changed the entire system to work with int arrays. Eliminated a bunch of other headaches, too. The working version of my MVC is:
#include <stdio.h>
#include <string.h>
int main (){
int nextChar;
int augmented[256];
int index = 0;
while ((nextChar = fgetc(stdin)) != EOF){
augmented[index] = nextChar;
index++;
}
for (int i = 0; i <= index;++i){
printf("%c", augmented[i]);
}
}
END EDIT
ORIGINAL POST:
I am trying to implement an LZW compressor for an assignment. So far, everything works great on text, but I am putting out garbage if the input file contains a long run of null characters.
Right at the start I store the incoming char as an int to check for EOF and then cast it to a char to concat to my augmented string for dictionary comparison. I have printed out my dictionary after each file and find that with long runs of zeros my dictionary entry is a null string.
I think that whats happening is that it takes a string of zeros and makes it a single zero. Not the desired value. I need to put out ALL those zeros.
I have made a minimal viable code to show the error and have found that it occurs right at the casting stage. How can I build a check for the null character so that I can substitute it for something else that can be stored in a string?
#include <stdio.h>
#include <string.h>
int main (){
int nextChar;
char augmented[256] = "\0";
while ((nextChar = fgetc(stdin) != EOF)){
char charBuffer[2];
sprintf(charBuffer, "%c", nextChar);
strcat(augmented, charBuffer);
}
printf("%s",augmented);
}
I've been searching for a couple days and I guess I can't seem to figure out what the correct query should be as I'm not finding any useful results.
The problem is parenthesis. Change to:
while ((nextChar = fgetc(stdin)) != EOF){
Your code assigned the value of the comparison fgetc(stdin)) != EOF to nextChar.
And you should also initialize charBuffer to zero.
here are some updates to your program. 0's are converted to '0's. Not exactly sure what you're looking for but hopefully this gets you pointed in the right direction:
#include <stdio.h>
#include <string.h>
int main (){
int nextChar;
char augmented[256] = {0}; // zero entire array
int i = 0;
while ((nextChar = fgetc(stdin)) != EOF){
// convert 0 to some other character
if( nextChar == 0 ) nextChar = '0';
augmented[i++] = (char)nextChar;
//check for buffer overflow
if( i==255) break;
}
printf("%s",augmented);
}

Error message - Invalid type argument of unary '*' (have 'int')

A program to convert a document into an array of strings.
#include <stdio.h>
#include <ctype.h>
#include <conio.h>
#include <string.h>
#include <stdlib.h>
main()
{
int i,j;
char *a[1000],c,*z;
z=a;
for(i=0;(c=getchar())!=EOF;i++)
{ if(c==' '||c=='\n')
{
z+=1;
i=0;
continue;
}
*(*(z)+i)=c;
}
}
I wanted to write a program to take input from the user and save the input as an array of words. But when I tried to run the code it showed the error earlier mentioned.
Thanks for the help.
Your pointer arithmetic is way off, and *a[1000] is an array of 1000 pointers, you really need something more like
int main(void) {
int i, j;
char a[1000][100], c;
i = 0, j = 0;
while ((c = getchar()) != EOF)
{
if (c == ' ' || c == '\n')
{
// should null terminate if you want to treat the words as strings
a[i][j] = '\0';
i++;
j = 0;
continue;
}
a[i][j++] = c;
}
}
This should store one word (up to 99 chars, as separated by space or newline char) in each of the 1000 arrays of 100 chars that a now holds.
You should of course add checks to make sure the 99 char limit per word and 1000 word limit is never exceeded.
First of all you should use int as return type for main(), as the default return type for main() is int.
Array name is itself a pointer so remove the pointer in array declaration: char *a[1000] to char a[1000].
Now just remove the pointer from z variable in line no.18 of your code:
*(*(z)+i)=c; to *((z)+i)=c;
Hope this helps to works out the code you wanted to.

C programming, meaningless figures on console [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I wrote code to reverse a sentence that the user inputs, but when I run this code and write a sentence, this code prints meaningless figures instead of reverse version of my sentence. I need helping locating the error
#include <stdio.h>
#include <string.h>
void reverser(char*);
int readmassage(char[], int);
int main()
{
char mysentence[30];
readmassage(mysentence, 30);
reverser(mysentence);
printf("%s", mysentence);
system("pause");
return 0;
}
void reverser(char *massage)
{
char temp,*p;
p = massage + strlen(massage)-1;
while (p > massage) {
temp = *massage;
*massage = *p;
*p-- = temp;
}
}
int readmassage(char massage[], int lenght)
{
int ch, i = 0;
while (ch = getchar() != '\n') {
if (lenght > i)
massage[i++] = ch;
}
massage[i] = '\0';
return i;
}
Your problem is here:
temp = *massage;
*massage = *p;
*p-- = temp;
massage always points to the first character in your string here. So you keep overwriting the first character, and then writing the new first character to the last character on the next go round. The effect is that you essentially rotate the string by one character instead of reversing it. If you change *massage = *p; to *massage++ = *p; (or create a new incrementing pointer variable to correspond to p which you initialize to massage), it'll probably work.
What I'm saying is that your "start of the string" pointer needs to be... massaged. ba dum chshhhh
EDIT: And you also need to change this, in readmessage:
while (ch = getchar() != '\n')
to:
while ((ch = getchar()) != '\n')
Otherwise, rather than the input character, you're actually setting ch to 0 or 1, depending on whether getchar() is returning '\n' or not. This is because due to the order of operations, != actually gets executed before =, and != gives you 1 if the expression is true and 0 if it is false. This 0 or 1 then gets stored in ch by the = operator.
You could also just replace all of readmessage with fgets, as it's included in the standard library and meant for exactly this sort of thing (unless reimplementing it was part of your assignment, of course).
EDIT:
Adding explanation. There are some issues with your code, few major, few not that serious
Don't use void main(). It's not the best thing to use.
Indenting your code will make it easier to read
Let's look at the readmassage function.
You are assigning the result of getchar() to an int. That's not right. it should be a char
here's a version of your code with minor fixes
#include <stdio.h>
#include <string.h>
void reverser(char*);
int readmassage(char[], int);
void main()
{
char mysentence[30];
readmassage(mysentence, 30);
printf("Input: %s", mysentence);
reverser(mysentence);
printf("Output: %s", mysentence);
system("pause");
return 0;
}
void reverser(char*massage)
{
char temp,*p;
p = massage + strlen(massage)-1;
while (p > massage) {
temp = *massage;
*massage = *p;
*p-- = temp;
}}
int readmassage(char massage[], int lenght)
{
char ch;
int i = 0;
while (ch != '\n')
{
ch = getchar();
printf("Here\n");
if (lenght > i)
{
massage[i++] = ch;
printf("%c\n", massage[i]);
}
}
massage[i] = '\0';
return i;
}
When you try this you will find that the input string gets read fine, just be sure to not to hi Enter after every character and instead type the full string out as \n is a valid character that can be in the stream and will terminate the loop the next iteration.
This is why you should use a char array reading function like fgets.
Once you get here you can see that the reverser is just following a slightly flawed reversing logic.
grammatical errors aside, fixing this you can get
here you go
#include <stdio.h>
#include <string.h>
void reverser(char* message)
{
int start, end;
start = 0;
end = strlen(message) - 1;
char temp;
while (start < end) {
temp = message[start];
message[start] = message[end];
message[end] = temp;
start++;
end--;
}
}
void readmessage(char message[], int length)
{
fgets(message, length , stdin);
}
int main()
{
char mysentence[30];
readmessage(mysentence, 30);
printf("Read the string\n");
reverser(mysentence);
printf("%s\n", mysentence);
return 0;
}
please debugg to find out the reason sometimes.. It will help you..
The problem is when you call readmassage(mysentence, 30) inside the function you have the string input.
When the flow comes back to the method the value is no more there as you had passed mysentence by value..
And you send null to reverse()..
Pass by reference will work..

Writer inserting unwanted newline character

I have 2 C functions that interact with one another. The first a writer function takes an int n and writes "Hellohello" n number of times. The reader function reads whatever is input to it, and every 50 characters inserts a newline character.
My current dilemma is that when I have a number of characters that is a factor of 50 my reader is putting an extra newline character in when I do not want it to. I have tried multiple different ways to remedy this and nothing I have attempted has worked as of yet. What I'm providing is my reader code without any of my attempted fixes as well as an example of what the problem is.
I do have to use getchar and putchar, I understand that there would be easier ways if I wasn't using them but it is unfortunately a must. Any assistance as to how I should approach this or something I should have thought about are greatly appreciated.
reader code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int count = 0;
char c;
while (c != EOF)
{
c = getchar();
if (count == 50)
{
putchar('\n');
count = 0;
}
putchar(c);
count++;
}
}
example output:
[88] [cbutc1#courses2016:~/csc412]$ writer 10 | reader1
HellohelloHellohelloHellohelloHellohelloHellohello
HellohelloHellohelloHellohelloHellohelloHellohello
▒[89] [cbutc1#courses2016:~/csc412]$
edit: clarity
When you read (getchar) a newline you print a newline (putchar).
Also, 'c' should be declared 'int'' so it is big enough to hold EOF properly.
Also the value of 'c' is undefined the first time through the loop and you print "EOF'", use:
while ((c = getchar()) != EOF) { …
Additionally, you should use int main ( void ) { …
And the C language does have "classes", only functions.
Simply changed the if statement that was checking the count to include a check for newline characters. This remedied the problem that was occuring.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int count = 0;
char c;
while (c != EOF)
{
c = getchar();
if ((count == 50) && (c != '\n'))
{
putchar('\n');
count = 0;
}
putchar(c);
count++;
}
}

printing a paragraph using putchar()

Consider the following code:-
#include"stdio.h"
void main()
{
char ch;
while((ch=getchar())!=EOF)
{
putchar(ch);
}
}
Whatever input I give to (as a sentence) it is repeated after I hit return key. What should I do if I want to get the entire paragraph at the end ? Can this be done using putchar() because putchar() can be used only to return a single character.
This won't work, since EOF doesn't fit in a char. Note that the proper return type of getchar() is int. See for instance this manual page.
If you want to read in a whole line at once, you can use fgets() into a character buffer for instance. I'm not sure I'm understanding exactly what you want to achieve, though.
EOF should be used when reading from files as the files end with a special EOF(end of file) character.You need to use any sentinel here to represent end of input.
this program makes a very little sense and I cant picture the use of this anywhere. So rethink about the requirements and change the logic accordingly.
may this code help you
char *buffer;
int i = 255;
buffer = (char *)malloc(i*sizeof(char));
*buffer = getchar();
while ( *buffer != '?' )
{
buffer++;
*buffer = getchar();
}
Try to store your char into a buffer and the when quit the while loop print the buffer. Try this code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int c;
char *buf = calloc(1,sizeof(char));
int len;
while ((c=getchar())!=EOF) {
len = strlen(buf);
buf = realloc(buf, len+1);
buf[len] = (char) c;
buf[len + 1] = '\0';
}
printf("%s",buf);
}
If you want to get entire paragraph at end, you should store the input in a buffer while EOF reaches. then print content of buffer in a loop. Also as Mr. Unwind's answer says make, ch variable a int, char is wrong!
#include"stdio.h"
#define SIZE 1024
void main()
{
int buffer[SIZE]
int ch;
int i=0;
// Read and store in a buffer
while((ch=getchar())!=EOF)
{
buffer[i] = ch;
i++;
}
buffer[i] = EOF;
// now print using putchar(ch);
i = 0;
while((ch = buffer[i]) !=EOF)
{
putchar(ch);
i++;
}
}
cose all we did in console/terminal - until we dont hit Enter/Return/^J/^M shell not send line to our program
u can get paragraph(more then 1 line) by copy and paste some lines so terminal|console program show 1st u pasted then repeated - output of u program

Resources