I am reading over the K&R book, and am a little stuck.
What is wrong with the following?
void getInput(int* output) {
int c, i;
for(i=0; (c = getchar()) != '\n'; i++)
output[i] = c; // printf("%c", c) prints the c value as expected
output[++i] = '\0';
}
When I run the program it never gets out of the loop and I have to Ctrl+C to exit. However if I replace the fifth line with printf("%c", c);, it prints out all the input just fine after hitting enter and creating the new line.
What is wrong with the following?
1. void getInput(int* output) {
Why is the input argument an int* when what you want to store in an array of characters?
Probably
void getInput(char* output) {
is better.
Also, how do you know that the output pointer is pointing somewhere where you hold enough memory to write the user's input? Maybe you must have the maximum buffer length as an extra parameter to avoid buffer overflow errors as PW pointed out.
5. output[++i] = '\0';
i has already been incremented an extra time inside the for loop, so you can just do:
output[i] = '\0';
Other than these, the program runs fine and outputs what we input until return.
FWIW, I tested it by calling it like so:
int main(void)
{
char o[100];
getInput(o);
printf("%s", o);
return 0;
}
It looks correct to me as written except that you don't need to increment i outside of the loop. The i gets incremented right before the loop exits, thus it is already where you want it.
Make sure that a '\n' is actually making it into c.
Sometimes an '\n' will get thrown away as a delimiter.
your last code as posted have 3 errors I can see:
char* userInput[MAX_INPUT_SIZE];
Should be:
char userInput[MAX_INPUT_SIZE+1];
(this was already mentioned by Pax Diablo)
getInput(&userInput);
Should be:
getInput( userInput );
This last error means you passed to getInput an address inside your call stack. you have a memory overwrite. probably one of your calls to getchar() returnes to the wrong address.
a simple way to risk buffer overflow, because output's size is never passed/checked
Have you tried using a debugger? You should step through the code in gdb or visual studio or whatever you are using and see what is going on. You said you were a beginner so maybe you hadn't considered that yet - this is a pretty normal debugging technique to use.
Here is the complete program with a couple of updates from your input, but it still won't make it out of the loop. BTW this was exercise 1-24 on pg 34
#include <stdio.h>
#define STACK_SIZE 50
#define MAX_INPUT_SIZE 1000
#define FALSE 0
#define TRUE 1
void getInput();
int validInput();
int main() {
char* userInput[MAX_INPUT_SIZE];
getInput(&userInput);
if (validInput(&userInput) == TRUE)
printf("Compile complete");
else
printf("Error");
}
// Functions
void getInput(char* output) {
int c, i;
for(i=0; (c = getchar()) != '\n' && c != EOF && i <= MAX_INPUT_SIZE; i++)
output[i] = c;
output[i] = '\0';
}
int validInput(char* input) {
char stack[STACK_SIZE];
int c;
int j;
for (j=0; (c = input[j]) != '\0'; ) {
switch(c){
case '[': case '(': case '{':
stack[j++] = c;
break;
case ']': case ')': case '}':
if (c == ']' && stack[j] != '[')
return FALSE;
else if (c == '}' && stack[j] != '{')
return FALSE;
else if (c == ')' && stack[j] != '(')
return FALSE;
// decrement the stack's index
--j;
break;
}
}
return TRUE;
}
Here is the final working code. I must say I picked up quite a bit from doing this one. Thanks for the help and pointers.
Any suggestions on how things could be done better?
#include <stdio.h>
#define STACK_SIZE 50
#define MAX_INPUT_SIZE 1000
#define FALSE 0
#define TRUE !FALSE
void get_input();
int valid_input();
int main() {
char user_input[MAX_INPUT_SIZE + 1]; // +1 for the \0
get_input(user_input);
if (valid_input(user_input))
printf("Success\n");
else
printf("Error\n");
}
// Functions
void get_input(char* output) {
int c, i;
for(i=0; (c = getchar()) != '\n' && c != EOF && i <= MAX_INPUT_SIZE; i++)
output[i] = c;
output[i] = '\0';
}
int valid_input(char* input) {
char stack[STACK_SIZE];
char c;
int i = 0;
int stack_index = -1;
while ((c = input[i]) != '\0' && i < STACK_SIZE) {
switch(c){
case '[': case '(': case '{':
stack_index++;
stack[stack_index] = c;
break;
case ']': case ')': case '}':
if ((c == ']' && stack[stack_index] != '[') ||
(c == '}' && stack[stack_index] != '{') ||
(c == ')' && stack[stack_index] != '('))
return FALSE;
// decrement the stack's index now that the closing bracket is found
stack_index--;
break;
}
i++;
}
// stack index should be back where it started
return (stack_index == -1);
}
Related
So I'm trying to do a program that reads a sequence of numbers separated by spaces and new lines. The output should be the same sequence, but erasing unnecessary zeros(The sequence of charachters 'EOF' ends the program). Per example
01492 102934 should come out as 1492 102934
9312 0 01923 should come out as 9312 0 1923
0001249 0000 should come out as 1249 0
Well I've achieved that purpose but have come across a roadblock. The program doesn't exit unless I type the EOF sequence. Maybe it's because I have a while(1) running that gives an infinite loop. But when I try to delete it the program doesn't even print at all. I'm still learning this is for a school project.
Any help would be apreciated!
Here's the code:
#include <stdio.h>
int main(){
char c;
int i=0;
while(1){
c=getchar();
if (i==0){
if(c=='0'){
while (c=='0'){
c=getchar();
}
}
printf("%c",c);
i=i+1;
}
else if (c==' '){
printf("%c",c);
c=getchar();
if(c=='0'){
while (c=='0'){
c=getchar();
}
}
printf("%c",c);
}
else if (c=='E'){
c=getchar();
if (c=='O'){
c=getchar();
if(c=='F'){
printf("\n");
return 0;
}
}
}
else{
printf("%c",c);
}
}
}
The important stuff:
int c; // IMPORTANT, cannot be char
while (1) {
c = getchar();
if (c == EOF) break; // exit loop
// ...
}
There has to be some way to tell the program to exit.
With this, the program will exit on the letter x or two consecutive newlines or entering END.
getchar will return EOF when there is nothing left to read from a file. That can be simulated from stdin ( the keyboard) with ctrl + z on Windows or ctrl + d on Linux.
#include <stdio.h>
#include <string.h>
int main ( void) {
char done[4] = "";
int c = 0;
int prior = 0;
int reading = 0;
int zero = 1;
while ( EOF != ( c = getchar ( )) && 'x' != c) {
if ( '\n' == c && '\n' == prior) {
break;
}
if ( c >= '0' && c <= '9') {
reading = 1;
if ( '0' != c) {
zero = 0;
}
if ( ! zero) {
putchar ( c);
}
}
else {
if ( reading) {
if ( zero) {
putchar ( '0');
}
if ( ' ' == c || '\n' == c) {
putchar ( c);
}
else {
putchar ( ' ');
}
}
reading = 0;
zero = 1;
}
prior = c;
done[0] = done[1];
done[1] = done[2];
done[2] = c;
done[3] = 0;
if ( 0 == strcmp ( done, "END")) {
break;
}
}
putchar ( '\n');
return 0;
}
getchar() returns an int, not a char. If it only returned a char, there would be no way for it to return a value that indicates end of file, since all char values are valid and can’t be used for another purpose.
A motivating example in decimal system may be: A function checks the temperature returns a two-digit number. Any temperature between 0 and 99 is valid. How do you report errors when the thermometer is disconnected? You have to return a number with more digits, and use a special value like UNPLUGGED = 100.
But int is a wider type: it has many more values than char, and the “extra” values can be used to indicate some special condition that means “hey, this is not a valid character, but something else I had to tell you”.
getchar() returns the EOF constant upon failure (any failure), for example if no more input is available. There’s nothing sensible you can do even if the reason for the failure other than end of input. You should end processing at the first EOF.
Thus, change the type of c to int, and every time you call getchar(), you must check that its value is not EOF, and return when you encounter it.
The nested structure of your loops means that EOF checking has to be repeated all over the place. There are other ways to structure the code to keep this check in one place, but, admittedly, the nested loops have at least the potential to exploit the branch predictor, whereas a single getchar followed by a state-machine style switch statement will make it perform potentially worse. None of this matters in a simple homework problem, but it’s something to keep in mind. In any case, performance has to be benchmarked - no other way around it.
Try this code, I think it does what you requested:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
static int getLine(char *prmpt, char *buff, size_t sz) {
int ch, extra;
// Get line with buffer overrun protection.
if (prmpt != NULL) {
printf("%s", prmpt);
fflush(stdout);
}
if (fgets(buff, sz, stdin) == NULL)
return -2;
// If it was too long, there'll be no newline. In that case, we flush
// to end of line so that excess doesn't affect the next call.
if (buff[strlen(buff) - 1] != '\n') {
extra = 0;
while (((ch = getchar()) != '\n') && (ch != EOF))
extra = 1;
return (extra == 1) ? -1 : 0;
}
// Otherwise remove newline and give string back to caller.
buff[strlen(buff) - 1] = '\0';
return 0;
}
int* convert2numbers(char* arr, int size) {
int i;
int j;
int k;
char token[100];
int* numbers;
int last_space = 0;
int index = 1;
int amount = 1;
// Count the amount of tokens.
for (i = 0; i < size; ++i) {
if (arr[i] == ' ') {
++amount;
}
}
numbers = (int *)malloc(amount * sizeof(int));
numbers[0] = amount;
for (j = 0; j <= size; ++j) {
if (arr[j] == ' ' || arr[j] == '\0') {
// Copy token from input string.
for (k = 0; k < j; ++k) {
token[k] = arr[k + last_space];
}
token[j] = '\0';
numbers[index] = atoi(token);
// Clear the token and continue.
memset(token, '\0', sizeof(token));
last_space = j;
++index;
}
}
return numbers;
}
int main(void) {
int i;
int size;
int* numbers;
int amount;
char input[100];
char help[] = "Numbers> ";
printf("Input numbers below or press enter to exit!\n");
while (1) {
getLine(help, input, sizeof(input));
// If input is empty exit.
if (input[0] == '\0') {
break;
}
size = strlen(input);
numbers = convert2numbers(input, size);
amount = numbers[0];
for (i = 1; i < amount + 1; ++i) {
printf("%d ", numbers[i]);
}
printf("\n");
}
return 0;
}
When run with these inputs this code outputs:
Input numbers below or press enter to exit!
Numbers> 01492 102934
1492 102934
Numbers> 9312 0 01923
9312 0 1923
Numbers> 0001249 0000
1249 0
Also if you press enter in console, it exits, as to escape the while(1) loop, easily.
I'm writing a function that replaces blank spaces into '-' (<- this character).
I ultimately want to return how many changes I made.
#include <stdio.h>
int replace(char c[])
{
int i, cnt;
cnt = 0;
for (i = 0; c[i] != EOF; i++)
if (c[i]==' ' || c[i] == '\t' || c[i] == '\n')
{
c[i] = '-';
++cnt;
}
return cnt;
}
main()
{
char cat[] = "The cat sat";
int n = replace(cat);
printf("%d\n", n);
}
The problem is, it correctly changes the string into "The-cat-sat" but for n, it returns the value 3, when it's supposed to return 2.
What have I done wrong?
#4386427 suggested this should be another answer. #wildplasser already provided the solution, this answer explains EOF and '\0'.
You would use EOF only when reading from a file (EOF -> End Of File). See this discussion. EOF is used to denote the end of file, and its value is system dependent. In fact, EOF is rather a condition than a value. You can find great explainations in this thread. When working with char array or a char pointer, it will always be terminated by a '\0' character, and there is always exactly one of those, thus, you would use it to break out of the loop when iterating through an array/pointer. This is a sure way to ensure that you don't access memory that is not allocated.
#include <stdio.h>
int repl(int c);
int main(void){
int c, nc;
nc =0;
while ((c=getchar())!=EOF)
nc = replc(c);
printf("replaced: %d times\n", nc);
return 0;
}
int replc(int c){
int nc = 0;
for(; (c = getchar())!=EOF; ++c)
if (c == ' '){
putchar('-');
++nc;
} else putchar(c);
return nc;
}
A string ends with a 0 (zero) value, not an EOF (so: the program in the question will scan the string beyond the terminal\0 until it happens to find a -1 somewhere beyond; but you are already in UB land, here)
[sylistic] the function argument could be a character pointer (an array argument cannot exist in C)
[stylistic] a pointer version wont need the 'i' variable.
[stylistic] The count can never be negative: intuitively an unsigned counter is preferred. (it could even be a size_t, just like the other string functions)
[stylistic] a switch(){} can avoid the (IMO) ugly || list, it is also easier to add cases.
unsigned replace(char *cp){
unsigned cnt;
for(cnt = 0; *cp ; cp++) {
switch (*cp){
case ' ' : case '\t': case '\n':
*cp = '-';
cnt++;
default:
break;
}
}
return cnt;
}
EOF used in the for loop end condition is the problem as you are not using is to check end of file/stream.
for (i = 0; c[i] != EOF; i++)
EOF itself is not a character, but a signal that there are no more characters available in the stream.
If you are trying to check end of line please use
for (i = 0; c[i] != "\0"; i++)
My code runs well to my surprise!!
The only problem is that whenever I use a bracketed infix input it comes out a 'J' at the end of postfix expression !! Any suggestions??
Here the algorithm is the basic one all expressions are getting converted and all is right but the tailing 'J' is i just cann't understand !! Suggestions??
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>
#define MAX 50
char stack[MAX];
int top = -1;
void push(char element)
{
stack[++top] = element;
}
char pop()
{
return(stack[top--]);
}
char tope()
{
return(stack[top]);
}
int prec(char c)
{
switch(c){
case '+':
case '-' : return 1;
break;
case '*' :
case '/' : return 2;
break;
default:
return 0;
break;
}
}
int main()
{
char post[MAX],in[MAX],ch,element;
printf("Infix expression : ");
scanf("%s",in);
int i=0,k=0;
in[strlen(in)] = ')';
push('(');
while((ch = in[i++]) != '\0')
{
if(isalnum(ch))
post[k++] = ch;
if(ch == '(')
push(ch);
if(ch == ')')
{
while(tope() != '(')
{
post[k++] = pop();
}
pop();
}
if(ch == '+' || ch =='-' || ch == '*' || ch == '/')
{
while(prec(ch) <= prec(tope()))
{
post[k++] = pop();
}
push(ch);
}
}
post[k] = '\0';
printf("%s",post);
return 0;
}
in[strlen(in)] = ')';
overwrites the nul-terminating character, which explains strange chars when printing (printing stops only when meeting another nul char by luck: undefined behaviour which may even lead to a crash if no nul char is found in the in 50-byte buffer)
You have to shift it, for instance like this:
int l = strlen(in);
in[l] = ')';
in[l+1] = '\0';
Note: you have to store the length of your string in l instead of calling strlen(in) twice not only because of the performance loss but, because putting the parenthesis means that strlen doesn't work properly until you null-terminate.
(also you probably want to protect your scanf like this: scanf("%48s",in); so you're sure to have enough room for the extra parenthesis for your 50-size buffer, even compatible with your macro definition, see scanf: template with macro (#define constant) inside)
Given a string of parentheses, write a program to find whether its valid or not.
Examples-
input : {{{}}}
output: Valid
input : }{}{}{}}
output: Invalid
I wrote the following code in C and tested that the output were coming correct.
#include <stdio.h>
#include <stdlib.h>
int main()
{
char str[20];
int i=0;
printf("Enter String: ");
gets(str);
int count = 0;
while (str[i] != '\0')
{
if (str[i] == '}')
count--;
if (str[i] == '{')
count++;
if (count < 0)
{
printf("\nInvalid");
break;
}
i++;
}
if (count == 0)
printf("\nValid");
return 0;
}
This program doesn't work for the case where input is {{{}}, what condition(s) am I missing?
Code should state if the final result is not 0 as in the case of "{"
if (count == 0) {
printf("Valid\n");
} else {
printf("Invalid\n");
}
return 0;
Also simple break out of loop.
if (count < 0) {
// printf("\nInvalid");
break;
}
gets() has been depreciated since C99 and eliminated from C (C11), use fgets().
char str[20];
fgets(str, sizeof str, stdin);
There is no need to read the entire string in. Code could use 1 char ar a time.
int ch;
while ((ch = fgetc(stdin)) != '\n' && ch != EOF) {
if (str[i] == '}')
count--;
if (count < 0) {
break;
}
else if (str[i] == '{')
count++;
}
}
You don't really need to input the whole string at once since you're only every sequentially processing the characters. Hence you can avoid using unsafe methods like gets() and even safe-but-complicating methods like fgets().
Instead, just use getchar() to read and process each individual character - that should greatly simplify what you need to do.
As to the logic, you basically have it right. Maintain the bracket level, a value initially set to zero. Then read each character and action it as follows:
If it's {, just add one to the level.
If it's }, subtract one from the level, then check to ensure the level is non-negative. If not, then you've had too many closing brackets and you can exit.
If it's end of line or end of file, stop processing characters. Check to make sure the final level is zero. If not, you haven't closed off all the brackets so it's invalid. If the level is zero, everything is balanced.
Any other character can be considered an error.
See below for one example on how to implement this:
#include <stdio.h>
int main (void) {
int debug = 0; // for debugging purposes.
int ch, level = 0; // character and current level.
// Output prompt, read characters while valid.
printf("Enter string: ");
while (((ch = getchar()) == '{') && (ch == '}')) {
// Select based on '{' or '}'.
if (ch == '{') {
// Open bracket, just add one.
++level;
if (debug) printf("DEBUG: {:%d\n",level);
} else {
// Close bracket, subtract one and check.
if (--level < 0) {
puts ("Level has gone below zero.");
return 1;
}
if (debug) printf("DEbug: }:%d ",level);
}
}
// If not endline/endfile, we have invalid character.
if ((ch != '\n') && (ch != EOF)) {
puts ("Invalid character in input.");
return 1;
}
// Level should be zero.
if (level != 0) {
puts ("Level still positive at end of line.");
return 1;
}
// All checks now passed okay.
puts ("Input was fine.");
return 0;
}
You should never use gets(), the gcc compiler even warns about it being dangerous because there is no way to prevent a buffer overflow, for example
char str[6];
gets(str);
with the following input
iharob
is a problem, because there is no room for the '\0' terminator or the '\n', instead
fgets(str, sizeof(str), stdin);
would be safe with any input, although the input string would be trimmed to fit the buffer, but no buffer overflow will occur.
Previous answers have covered avoiding buffer overflows and potential cases where it will not work - to improve performance I would modify the while loop to avoid checking conditions which we know will always be false. e.g. no point in checking if count is less than 0 unless we just decreased the count; no point in checking for an open bracket if the character was a close bracket:
while (str[i] != '\0')
{
if (str[i] == '}')
{
count--;
if (count < 0)
{
printf("\nInvalid");
break;
}
}
else if (str[i] == '{')
count++;
i++;
}
I hope you find this useful and simple ^-^
#include<iostream>
#include<string.h>
using namespace std;
{
string mathEx ;
cout<<"Please Enter math Expression contain ')' , '(' to
check balance \n"<<"MathExpression = ";
cin>>mathEx ;
int i =0 , count = 0 ;
while (mathEx [i] != '\0'){
if(mathEx[i]=='('){
count++;
}
if(mathEx[i]==')'){
count--;
}
if(count<0){
break ;
}
i++;
}
if(count==0){
cout<<"True !";
}
else {
cout<<"Invalid !"<<endl;
}
return 0;
}
I'm in my first programming class and having trouble with a project of ours. The program is designed to take a string's inputs and see if they match the pattern and recognize if the pattern is broken; in this case it is meant to recognize if the user inputs "hahaha!", "hohohoho!", or a mixture of the two 'ha' and 'ho' (always ending in '!').
My trouble is that I have started an attempt at this code using switch cases, but do not know if this is the most effective way to program for the project, or if it is even possible to do it this way.
Here is my code so far, please help me.
#include <stdio.h>
#include <string.h>
#define string_len 100
int main ()
{
char string[string_len];
int state = 0;
while(1)
{
for(int i = 0; i < string_len; i++)
{
printf("Hello, I can tell if you are laughing or not, you can exit by typing 'bye': \n");
scanf("%s", string);
for(state = 0; state < 5;)
{
switch(state)
{
case 0:
if(strcmp(string, "bye") == 0)
printf("Bye now!\n");
return 0;
break;
case 1:
if(string[i] == 'h')
state++;
else(printf("you are not laughing\n"));
break;
case 2:
if(string[i] == 'a')
state--;
else(state++);
break;
case 3:
if(string[i] == 'o')
state = state-2;
else(printf("you are not laughing\n"));
break;
case 4:
if(string[i] == '!')
printf("You are laughing!\n");
else(printf("You are not laughing\n"));
}
}
}
return 0;
}
}
I think that I may be mixed up with the state part of my program in the switch. I'm trying to allow it to go from:
state 0 : check if it says bye, if so "bye now"
state 1: is it an h? if so, check for a or o, if not "you arent laughing"
state 2: is it an a? if so, check for an 'h' or '!' -This is where I'm especially confused, if not is it an o?
state 3: is it an o? if so, check for an 'h' or '!', if not "you aren't laughing"
state 4: is it an '!'? if so "you are laughing" if not, "you are not laughing"
I hope I have formatted this question well enough, please let me know if I could make this more readable in any way and if you have any questions for me.
Thank you all for the help.
Since you asked if there might be another way preferable to a switch() statement, I decide to code an example of a way for you. This works for me. Should compile cleanly and run fine.
#include <stdio.h>
#include <string.h>
#define MAXLEN 100
char *readline();
int main(void) {
char string[MAXLEN];
for(;;) {
memset(string, '\0', MAXLEN);
printf("Hello, I can tell if you are laughing or not, you can exit by typing 'bye': \n");
readline(string, MAXLEN, stdin);
int i = 0;
int aborted = 0;
char buf[3] = { 0 };
while (i < strlen(string) - 1) {
buf[i % 2] = string[i];
if (i % 2 == 1) {
if (strncmp(buf, "ha", 2) != 0 && strncmp(buf, "ho", 2) != 0) {
printf("\nYou are NOT laughing [1]\n\n");
aborted = 1;
break;
}
}
i++;
}
if (!aborted) {
if (string[i] != '!') {
printf("\nYou are NOT laughing [2]\n\n");
continue;
}
printf("\nYou ARE laughing!\n\n");
}
}
}
char *readline (char *buf, size_t length, FILE *f) {
char *p;
if ((p = fgets (buf, length, f)) != NULL) {
size_t last = strlen (buf) - 1;
if (buf[last] == '\n') {
buf[last] = '\0';
} else {
fscanf (f, "%*[^\n]");
(void) fgetc (f);
}
}
return p;
}
The problem you are having is that you fail to remove the newline from stdin. Instead of:
scanf("%s", string);
You need:
scanf("%[^\n]%*c", string);
What happens is that you read your first input fine, but stdin still contains a newline '\n' (the result of pressing [Enter]). If you don't enter bye, when you reach scanf again, scanf takes the '\n' as your input. The new format string above "%[^\n]%*c" says %[^\n] read all characters up to the newline, then %*c read and discard the newline.
#include <stdio.h>
#define string_len 100
#define n2s_(n) #n
#define n2s(n) n2s_(n)
int main(void){
char string[string_len+1];
while(1){
printf("Hello, I can tell if you are laughing or not, you can exit by typing 'bye': \n");
scanf("%" n2s(string_len) "s", string);
if(strcmp(string, "bye") == 0)
break;
//match (ha | ho)+! ?
int i, match = 1, ch;
for(i = 0; match && (ch=string[i]) && ch != '!'; ++i){
if(i & 1){//odd position
if(string[i] != 'a' && string[i] != 'o'){
match = 0;
}
} else {//even position
if(string[i] != 'h'){
match = 0;
}
}
}
if(match && i != 0 && ch == '!')
printf("You are laughing!\n");
else
printf("You are not laughing\n");
}
return 0;
}