C programming, meaningless figures on console [closed] - c

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..

Related

does the pointer reallocate memory as it increments?

how can i stop *str from filling memory that i didnt give to it, without having to add an ending condition which in this case is : i <= n
do{
//instructions;
} while (... && i <= n);
in this exemple i reserved only 3 bytes of memory to *str but when i run my code and input more than 3 characters it still works... how does that happen shouldnt it give an error cuz there isnt enough memory for the rest of the characters ? what if the selected empty adresses were xxxxx1 xxxxx2 xxxxx3 and then xxxxx4 is full will it stop and output only the 3 characters without an error ?
P.s : I am aware of the function gets() but i dont want to use it because it reallocates memory. i thought that by entering character by character i will solve the problem and stop the user from filling the pointer because this time there is no memory reallocation and *str only has 3 blocks of memory so the rest will go to the buffer and *str will stop at *(str + 2)
hope u understood the problem and thank u for answering
#include <stdio.h>
#include <string.h>
#include <malloc.h>
int main()
{
int i = -1, n = 3;
char *str = (char *)malloc(n*sizeof(char));
printf("Enter a string: ");
do
{
i++;
str[i] = getchar();
} while (str[i] != '\n' && i < n);
str[i] = '\0';
printf("Entered string is: %s", str);
return 0;
}
C doesn't perform any type of bounds checking on arrays or allocated memory. That's part of what makes it fast.
That also means that reading or writing past the end of an array causes undefined behavior which basically means there's no guarantee what the program will do. The language trusts you to do the proper thing, so it's up to you to ensure that you don't do something you shouldn't.
Also, gets doesn't reallocate memory. In fact, it shouldn't be used at all specifically because it doesn't perform any bounds checking.
Your example doesn't work if the input string is longer than two characters since it then tries to write beyond the array. What will happen when you try to write outside of the array is undefined, which means that it may work by pure chance under some circumstances. Try this safe function instead which always reads the entire line and truncates the result if necessary:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void ReadLine(char result[], int resultLen)
{
int ch, i;
assert(resultLen > 0);
i = 0;
ch = getchar();
while ((ch != '\n') && (ch != EOF)) {
if (i < resultLen - 1) {
result[i] = ch;
i++;
}
ch = getchar();
}
result[i] = '\0';
}
int main(void)
{
int n = 3;
char *str = malloc(n);
printf("Enter a string: ");
ReadLine(str, n);
printf("Entered string is: %s\n", str);
free(str);
return 0;
}

Replacing `goto` with a different programming construct

I m trying to do this little programm with defensive programming but its more than difficult for me to handle this avoiding the Loop-Goto as i know that as BAD programming. I had try with while and do...while loop but in one case i dont have problem. Problem begins when i m going to make another do...while for the second case ("Not insert space or click enter button"). I tried and nested do...while but here the results was more complicated.
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int i;
int length;
char giventext [25];
Loop:
printf("String must have 25 chars lenght:\n");
gets(giventext);
length = strlen(giventext);
if (length > 25) {
printf("\nString has over %d chars.\nMust give a shorter string\n", length);
goto Loop;
}
/* Here i trying to not give space or nothing*/
if (length < 1) {
printf("You dont give anything as a string.\n");
goto Loop;
} else {
printf("Your string has %d\n",length);
printf("Letter in lower case are: \n");
for (i = 0; i < length; i++) {
if (islower(giventext[i])) {
printf("%c",giventext[i]);
}
}
}
return 0;
}
Note that your code is not defensive at all. You have no way to avoid a buffer overflow because,
you check for the length of the string after it has been input to your program so after the buffer overflow has already occurred and
you used gets() which doesn't check input length and thus is very prone to buffer overflow.
Use fgets() instead and just discard extra characters.
I think you need to understand that strlen() doesn't count the number of characters of input but instead the number of characters in a string.
If you want to ensure that there are less than N characters inserted then
int
readinput(char *const buffer, int maxlen)
{
int count;
int next;
fputc('>', stdout);
fputc(' ', stdout);
count = 0;
while ((next = fgetc(stdin)) && (next != EOF) && (next != '\n')) {
// We need space for the terminating '\0';
if (count == maxlen - 1) {
// Discard extra characters before returning
// read until EOF or '\n' is found
while ((next = fgetc(stdin)) && (next != EOF) && (next != '\n'))
;
return -1;
}
buffer[count++] = next;
}
buffer[count] = '\0';
return count;
}
int
main(void)
{
char string[8];
int result;
while ((result = readinput(string, (int) sizeof(string))) == -1) {
fprintf(stderr, "you cannot input more than `%d' characters\n",
(int) sizeof(string) - 1);
}
fprintf(stdout, "accepted `%s' (%d)\n", string, result);
}
Note that by using a function, the flow control of this program is clear and simple. That's precisely why goto is discouraged, not because it's an evil thing but instead because it can be misused like you did.
Try using functions that label logical steps that your program needs to execute:
char * user_input() - returns an input from the user as a pointer to a char (using something other than get()! For example, look at scanf)
bool validate_input(char * str_input) - takes the user input from the above function and performs checks, such as validate the length is between 1 and 25 characters.
str_to_lower(char * str_input) - if validate_input() returns true you can then call this function and pass it the user input. The body of this function can then print the user input back to console in lower case. You could use the standard library function tolower() here to lower case each character.
The body of your main function will then be much simpler and perform a logical series of steps that tackle your problem. This is the essence of defensive programming - modularising your problem into separate steps that are self contained and easily testable.
A possible structure for the main function could be:
char * user_input();
bool validate_input(char *);
void str_to_lower(char *);
int main()
{
char * str_input = user_input();
//continue to get input from the user until it satisfies the requirements of 'validate_input()'
while(!validate_input(str_input)) {
str_input = user_input();
}
//user input now satisfied 'validate_input' so lower case and print it
str_to_lower(str_input);
return 0;
}

String modification through function. Unexplained behavior

This Program should change n't followed by an alphabet to " not". like don't -> do not.
But it's showing some really weird outputs.
e.g if i just skip printing the string length output is garbage. also how space is changing to s2ace in output i can't say. If i didn't know better i'd say i have a ghost in the code.
#include<stdio.h>
#include<string.h>
#include<ctype.h>
int func(char **str, int cur_len, int max_len)
{
if (cur_len <= 3)
return(cur_len);
else if(max_len < cur_len)
return(-1);
int i,j;
char new[max_len];
new[0]='\0';
char temp[2];
for (i = 0; i < cur_len; i++)
{
if(i > 0 && i < cur_len - 2 && isalpha((*str)[i-1]) && (*str)[i] == 'n' && (*str)[i+1] == '\'' && (*str)[i+2] == 't')
{
strcat(new," not");
i=i+2;
}
else
{
temp[0]=(*str)[i];
temp[1]='\0';
strcat(new, temp);
}
}
j = strlen(new);
if (j > max_len)
return(-1);
*str = new;
return(j);
}
int main()
{
char *x = "Please don't do anything stupid. all the n't followed by an alphabate should be changed to not followed by a space. e.g. doesn't.";
int len, max, result;
len = strlen(x);
printf("String size = %d\n",len);//**if i comment this line all output goes down the drain.**
max = 200;
result = func (&x, len, max);
if(result == -1)
{
printf("No change possible\n");
return(-1);
}
printf("No of changes = %d\n",strlen(x)-len);
printf("New String is :: %s\n",x);//**how does space change into s2ace??**
return(0);
}
Output is
129No of changes = 2
New String is :: Please do not do anything stupid. all the n't followed by an alphabate should be changed to not followed by a s2ace. e.g. does not.
Fix the problem with minimal code changes by replacing char new[max_len]; with
char *new = *str = (char*)malloc(max_len+1);
You'll also need to add #include <stdlib.h> at the top.
As mentioned in comments, pointers to local objects (with auto storage class) become invalid as soon as the function returns.
Static objects won't disappear, but I don't believe that variable-length arrays are allowed to be static. So, you're stuck with malloc/calloc.
Be sure to document this behavior, so that the author of the calling function knows to free the pointer when the memory is no longer needed. (If you're going to quibble that you are the author and already know it, I'll point out that it helps the reader of your code to know what's going on.)

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

read string of character and assign it to an array

I don't know how to work with scanf and get the input of it for the entry of the function readBigNum I want to make array until the user entered the Enter and also I want to write a function for assigning it into an array and return the size of the large number
I want readBigNum to exactly have the char *n but I can not relate it in my function
#include <stdio.h>
int readBigNum(char *n)
{
char msg[100],ch;
int i=0;
while((ch=getchar())!='\n')
{
if(ch!='0'||ch!='1'||ch!='2'||ch!='3'||ch!='4'||ch!='5'||ch!='6'||ch!='7'||ch!='8'||ch!='9')
return -1;
msg[i++]=ch;
}
msg[i]='\0';
i=0;
return i;
}
int main()
{
const char x;
const char n;
n=scanf("%d",x);
int h=readBigNum(&n);
printf(h);
}
If I understand your question correctly, you want to implement a function that will read numbers from stdin storing them in a buffer. If a non-number is encountered, you want to return -1. If a new-line is encountered, you want to return the number of characters that were read. If that's correct, you'll probably want your code to look something like the following:
#include <stdio.h>
int readBigNum(char* n)
{
char ch;
int i=0;
while ((ch = getchar()) != '\n') {
if (ch < '0' || ch > '9') {
return -1;
}
n[i++] = ch;
}
n[i] = '\0';
return i;
}
int main(void) {
char buf[100];
int bytes = readBigNum(buf);
printf("%s\n", buf);
printf("%d\n", bytes);
};
The main differences from your implementation
The array to be populated is initialized in main and passed to the readBigNum function. This is a little simpler than having the function control the memory, in which case you would need likely need to deal with malloc and free. Even with this, you run the risk of a buffer overrun and will likely want to take additional precautions to prevent that.
The function does not set i to 0 before returning it. The original code could never return a value other than -1 (on error) or 0, which didn't appear to be the intent.
This code doesn't use scanf. Given your description of what you wanted to accomplish, using scanf didn't appear to be a good fit, however if you provide more information on why you were calling it might help to inform this answer.
The printf call was incorrect, it has been updated to print the number of bytes returned, and an additional printf call was added to print the updated buffer.
Remember that getchar() returns type int, not char. This is because the function may return EOF (which is defined as a negative integer with no particular value).
Also, for functions that deal with buffers, it is always a good idea to take an extra argument that describes the size of the array. This helps reduce buffer overruns because you know how far you can go. With your existing function, if the user types more than 100 characters, your buffer is overrun.
#include <stdio.h>
#include <ctype.h>
int readBigNum(char *n, size_t len)
{
int ch;
int i = 0;
// we make sure 'i' is less than 'len - 1' to leave space for '\0'
while((ch = getchar()) != EOF && i < (len - 1))
{
if (ch == '\n') // stop on linefeed
break;
else if (!isdigit(ch))) // abort on invalid character
return -1;
else
n[i++] = (char) ch;
}
msg[i] = '\0';
return i;
}
int main(void)
{
char buf[100];
int result = readBigNum(buf, sizeof buf);
if (result > 0)
printf("Length %d : %s\n", result, buf);
else
printf("Invalid number!\n");
}

Resources