Program won't execute function? - c

I have no idea what i'm doing wrong here, but I'm trying to make a vertical histogram program based on the length of strings input through the commad line using getchar() (one of The C Programming Language excercises), but something seems to be going wrong when I run it. The function printgraph() is supposed to print the histogram using the for loops shown by printing the graph, graph[][] line by line, where j increments the y axis and i increments the x axis. However, when I run this, the graph doesn't print when it reaches this line of code. I've revised the code and gone over it many times, and still haven't a clue. I know that this may also be a trivial question to some, and I apologize that I lack much experience, but all help is appreciated.
#include <stdio.h>
char graph[11][11];
void printgraph(){
int i, j;
char graph[11][11];
for(j = 0; j<=10; j++){
for(i = 0; i<=10; i++){
putchar(graph[i][j]);
}
printf("\n");
}
}
int main(){
char c, graph[11][11];
int i, j, onoroff, numchar[10];
for(i = 10; i>=0; i--)
graph[0][i] = i;
for(j=10;j>=0; j--)
graph[j][0] = j;
for(j=0;j<=9;i++)
numchar[j] = 0;
onoroff = 1;
i = 0;
while(graph[1][10] != 'O' || graph[2][10] != 'O' || graph[3][10] != 'O' || graph[4][10] != 'O' || graph[5][10] != 'O' || graph[6][10] != 'O' || graph[7][10] != 'O' || graph[8][10] != 'O' || graph[9][10] != 'O' ||graph[10][10] != 'O'){
while((c = getchar()) != EOF){
printgraph();
if(c == ' '|| c == '\n' || c == '\t'){
if(onoroff == 1){
numchar[i]++;
graph[i][numchar[i]+1] = 'O';
}
onoroff = 0;
i = 0;
}else if(onoroff == 1){
i++;
}else if(onoroff == 0){
onoroff = 1;
i++;
}
}
}
return 0;
}

It never reaches the printgraph function since you are getting stuck in the third for loop.
for(j=0;j<=9;i++)
numchar[j] = 0;
You are incrementing i but testing j
Also see the answer from NPToita

it's because you have 3 variables named graph;
the global graph variable is never used because the main function has its own local variable graph which it writes to and printgraph has its own version of graph variable which it reads from.
can you try deleting the graph variables declarations from the main and printgraph functions and see what happens?

Related

Count words without vowels in a given list in c

I am trying to count the words that do not contain any vowel in a given list. Here's my code:
int noVowel(char * List[], int nSize){
int i, j, count = 0;
for(i=0; i<nSize; i++){
for(j=0; j<strlen(List[j]); j++){
if(*List[j]!='a' || *List[j]!='e' || *List[j]!='i' || *List[j]!='o' || *List[j]!='u')
count++;
}
}
return count;}
List[] is the list of words I have to check.
nSize is the number of words listed in the List[].
I would like to ask for help in returning the number of words without vowels. I apologize for the confusing code as I am new to programming.
Here is a correction of your code:
#include <stdio.h>
#include <string.h>
int isVowel(char c) {
if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c =='u' || c =='y')
return (1);
else
return (0);
}
First, here is a function that tells you if a character is a vowel by returning 1 (if it is not a vowel, it returns 0).
int noVowel(char *List[], int nSize){
int i, j, count = 0;
for(i = 0; i < nSize; i++) {
for(j = 0; j < strlen(List[i]); j++) {
if (isVowel(List[i][j]) == 1)
break ;
}
if (List[i][j] == '\0')
count++;
}
return count;
}
Secondly, like you, I did two loops to go through all the characters of my strings. If I find a vowel, I break, which means I go outside the current loop. If I am outside the second loop, I want to know if I have been able to go to the end of the string. If yes, I did not find any vowel, so I can increment my count int.
There was a mistake in your implementation of the 2 loops. By running this version displaying characters one by one you should see that there is an issue.
for(i=0; i<nSize; i++){
for(j=0; j<strlen(List[j]); j++){
printf("%c", List[i][j]);
}
printf("\n");
}
P.S.: Indentation is important in programming it makes your code readable easily. At my school we use the following conventions https://cdn.intra.42.fr/pdf/pdf/960/norme.en.pdf (you should not apply all the rules they propose, but some of them are good practices)

is there any way to stop a (c = getchar()) != EOF) if my work inside the while loop is done?

I am reading the C programming language book Dennis M. Ritchie and
trying to solve this question:
Write a program to print a histogram of
the lengths of words in
its input. It is easy to draw the histogram with the bars horizontal; a vertical
orientation is more challenging.
I think my solution works, but the problem is that if I don't press EOF, the terminal won't show the
result. I know that the condition specifies that exactly, but I am
wondering whether there is any way to make the program terminate after
reading a single line? (Sorry if my explanation of the problem is a bit shallow. Feel free to ask more.)
#include <stdio.h>
int main ()
{
int digits[10];
int nc=0;
int c, i, j;
for (i = 0; i <= 10; i++)
digits[i] = 0;
//take input;
while ((c = getchar ()) != EOF) {
++nc;
if (c == ' ' || c=='\n') {
++digits[nc-1];
//is it also counting the space in nc? i think it is,so we should do nc-1
nc = 0;
}
}
for (i = 1; i <= 5; i++) {
printf("%d :", i);
for (j = 1; j <= digits[i]; j++) {
printf ("*");
}
printf ("\n");
}
// I think this is a problem with getchar()
//the program doesn't exit automatically
//need to find a way to do it
}
You could try to make something like
while ((c = getchar ()) != EOF && c != '\n') {
and then adding a line after the while loop to account for the last word:
if (c == '\n') {
++digits[nc-1];
nc = 0;
There is also another problem inside your program. ++digits[nc-1]; is correct, however, for the wrong reason. You should make it because an array starts at zero, i.e. if you have an array of length 10, it will go from 0 to 9, so you should count the length of the words and then add one to the position of the array length - 1 (as there are no words of length zero). The problem is that you are still counting the blank spaces or the newline characters inside the length of a word, so if you have two blank spaces after a word of length 4, the program will add to the array a word of length 5 + a word of length 1. To avoid this, you should do something like this:
while ((c = getchar ()) != EOF) {
if ((c == ' ' || c == '\n' || c == '\t') && nc > 0) {
++digits[nc-1]; // arrays start at zero
nc = 0;
}
else {
++nc;
}
}

change output from character array

Once again i find myself relatively lost and seeking knowledge from my peers.
What I am needing to do is to write a program that takes in an encoded language that adds the leters 'u' 't' after ever consonant and output into english. So the input Hutelutluto would be outputted as hello. At first I thought i had it figured out, but then my professor said i had to store the initial input in a character array and display it. Then use that character array to output the modified translation.
I have tried several different angles, one trying to modify my readstring function to fit my modification parameters. It always ends up becoming a mess and giving me unexpected outputs.
Essentially I believe that I need help feeding the character array into the while loop, but when I try I get an error stating that i have a pointer comparison to integer error.
Here is my edition of my code where i believe I was the closest to solving the problem. At the moment the while works independently from the readstring function. I am sure I am overthinking the problem, but i just not sure how to work out the kinks.
:
/*
Tut language
By: Steven
*/
# include <stdio.h>
void readstring(char *, int);
int main (void){
char input [50];
char output;
char trash;
//initiation
printf("\n\t*Hi! Welcome to the assemble of Tut*\n");
printf("I can help you decode/encode a message to and from the code called Tut!\n");
printf("Enter a sentence to be translated frome Tut - English: ");
readstring(input, 50);
printf("Your Tut sencence is: %s \n",input);
while (output != '\n') {
output = getchar();
if(output == '\n'){//escape sequence
break;
}
if((output != 'a') && (output != 'e') && (output != 'i') && (output != 'o') && (output != 'u') && (output != 'y') && (output != ' ')){
putchar(output);
trash = getchar();
trash = getchar();
}else{
putchar(output);
}
}
return 0;
}// end main
//function lists start
void readstring(char * buffer, int size) {
int x;
char c = getchar( );
if( c == '\n' ) {
c = getchar( );
}
for(x = 0 ; (x < (size-1)) && c != '\n' ; x++) {
buffer[x] = c;
c = getchar( );
}
buffer[x] = '\0';
}
Any help or feedback will be greatly appreciated!
Thank your for your time!
p.s.
After taking your advice into consideration i edited my code, but it seems as if it is ignoring all input after the first. I even tried changing the !='\n' condition to just i < 50, but i got the same results.
Line of code after taking Tim's advice:
for (i = 0; input [i] != '\n'; ++i){
output = input[i];
if((output != 'a') && (output != 'e') && (output != 'i') && (output != 'o') && (output != 'u') && (output != 'y') && (output != ' ')){
putchar(output);
trash = getchar();
trash = getchar();
}else{
putchar(output);
}
}
The main problem is in your while loop. In this loop, you are using getchar, which tries to read from stdin. However, you have already read your input, and it is stored in buffer.
So, you should get your characters from buffer instead of reading them again.
Your readstring function already calls getchar to read characters from the user's terminal, so you should not need to call it again after readstring is done. Instead, use a for loop to set output to each character of the input string in turn:
int i;
for i = 0; input[i] != '\n'; ++i {
output = input[i]
if((output != 'a') && (output != 'e') && (output != 'i') && (output != 'o') && (output != 'u') && (output != 'y') && (output != ' ')){
...
… in a character array, i have no idea how I am going to skip
those next two character?
You skip characters by incrementing the array index. Change
trash = getchar();
trash = getchar();
to
input[++i] && input[++i] || --i; // step back if at end of string
Also, since the input string is terminated by \0 rather than \n, change
for (i = 0; input [i] != '\n'; ++i){
to
for (i = 0; input[i]; ++i)
{

Can't assign value to a variable inside a for loop

Here is what I want to do:
Read all characters from a '.c' file and store that into an array.
When a character from that array is '{', it will be pushed into a stack. And count of pushed characters will be increased by 1.
When a character from that array is '}', stack will pop and the count of popped characters will be increased by 1.
Compare those two counts to check whether there is a missing '{' or '}'
Here is my code:
int getLinesSyntax(char s[], int limit, FILE *cfile)
{
int i, c, push_count = 0, pop_count = 0;
int state = CODE;
int brackets[limit];
char braces[limit];
for(i = 0; i < 100; i++)
{
braces[i] = 0;
}
for(i = 0; i < limit - 1 && (c = getc(cfile)) != EOF && c != '\n'; i++)
{
s[i] = c;
if(s[i] == '{')
{
braces[0] = s[i];
//push(s[i], braces);
++push_count;
}
else if(s[i] == '}')
{
pop(braces);
++pop_count;
}
}
//Mor shiljih uyed array -n togsgold 0-g zalgana
if(c == '\n')
{
s[i] = c;
i++;
}
s[i] = '\0';
i = i -1; //Suuld zalgasan 0 -g toonoos hasna
if(c == EOF)
{
//just checking
for(i = 0; i < 100; i++)
{
printf("%d", braces[i]);
}
if(push_count != pop_count)
{
printf("%d and %d syntax error: braces", push_count, pop_count);
}
return -1;
}
else
{
return i;
}
}
Here is the output
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
The problems is:
Assignments inside the for loop is not working. (It's working when I put that outside of the loop)
I would like to know if there's something wrong with my code :).
There are several problems.
Lets go through it step by step
1) Your array initialization loop:
int brackets[limit];
char braces[limit];
for(i = 0; i < 100; i++)
{
braces[i] = 0;
}
You declare the array having size of limit but only initialize 100 items. Change 100 to limit to fully initialize it depending on the parameter of the function.
2) The conditional statement of the main for loop:
i < limit - 1 && (c = getc(cfile)) != EOF && c != '\n'
Although the first substatement is correct I have two remarks:
Firstly (c = getc(cfile)) != EOF might be one reason why the loop is never accessed and still everything is 000000.... Check if the file exists, the pointer is not NULL or other silent errors occured.
Secondly the c != '\n'. What if one of these characters occurs? In this case you won't continue with the next iteration but break out of the entire forloop. Remove it there and put it in the first line of the body like this:
if(c == '\n')
{
i -= 1; // to really skip the character and maintain the index.
continue;
}
3) s[i] = c;
Can you be certain, that the array is indeed sizeof limit?
4) Checking for curly braces
if(s[i] == '{')
{
braces[0] = s[i];
//push(s[i], braces);
++push_count;
}
else if(s[i] == '}')
{
pop(braces);
++pop_count;
}
You assign to braces[0] always, why?
5) Uninitialized access
if(c == '\n')
{
s[i] = c;
i++;
}
s[i] = '\0';
i = i -1; //Suuld zalgasan 0 -g toonoos hasna
You're now using the function-global variable i, which is never initialized properly for this block. What you do is to use a variable that is used basically everywhere ( which is basically also no problem from the memory point of view. ), but you rely on legacy values. Is this done by purpose? If no, reinitialize i properly. I have to ask this since i can't read your comments in code.
What I'm quite unhappy about is that you entirely rely on one variable in all the loops and statements. Usually a loop-index should never be altered from inside. Maybe you can come up with a cleaner design of the function like an additional index variable you parallelly increase without altering i. The additional index will be used for array access where appropriate whereas i really remains just a counter.
I think the problem is in this condition "c != '\n'" which is breaking the for loop right after the first line, before it reaches any brackets. And hence the output.
For the task of counting whether there are balanced braces in the data, the code is excessively complex. You could simply use:
int l_brace = 0;
int r_brace = 0;
int c;
while ((c = getchar()) != EOF)
{
if (c == '{')
l_brace++;
else if (c == '}')
r_brace++;
}
if (l_brace != r_brace)
printf("Number of { = %d; number of } = %d\n", l_brace, r_brace);
Of course, this can be confused by code such as:
/* This is a comment with an { in it */
char string[] = "{{{";
char c = '{';
There are no braces that mark control-of-flow statement grouping in that fragment, for all there are 5 left braces ({) in the source code. Parsing C properly is hard work.

Kernighan and Ritchie Exercise 2-2 Debugging?

I am working through K&R (2nd edition) for my own edification and encountered the following exercise (exercise 2-2 p42):
Write a loop equivalent to the following without using && or ||:
for (i=0; i<lim-1 && (c=getchar()) != '\n' && c != EOF; ++i)
s[i] = c;
This was my solution:
#include <stdio.h>
/* write a loop equivalent to the following without using && or ||
for (i=0; i<lim-1 && (c=getchar()) != '\n' && c != EOF; ++i)
s[i] = c;
*/
int main()
{
int counter = 0, lim = 1000;
int s[lim], c;
while(counter < lim-1)
{
while((c = getchar()) != '\n')
{
while(c != EOF)
{
s[counter] = c;
}
}
counter++;
}
return 0;
}
I was expecting the indented loops and therefore the entire program to exit normally once it encountered a newline character ('\n') or an EOF character (Ctrl-d on my Linux machine), but to my surprise it happily soldiers on. I tried to debug it using gdb but still could not figure it out.
What am I not seeing?
Addendum: I tried to reverse the sequence of tests the while loops perform and added an if statement to break out of the outer loop if c == '\n' but am still not seeing it! I am also having difficulty trying to run GDB entering text into the command line and simultaneously printing the value of c, even when I tried to link gdb to the pid of a running copy of the executable. I realize that there are probably other ways to solve this exercise, e.g. setting an OK_TO_EXECUTE flag or variable that is true only if all three conditions are met, but I am bothered by the fact that I seem unable to find the bug in a seemingly simple program. This is precisely why I am returning to K&R to go through the book more thoroughly and to solve the exercises properly.
Redone code (still buggy!!!):
#include <stdio.h>
/* write a loop equivalent to the following without using && or ||
for (i=0; i<lim-1 && (c=getchar()) != '\n' && c != EOF; ++i)
s[i] = c;
*/
int main()
{
int counter = 0, lim = 1000;
int s[lim], c;
while((c = getchar()) != EOF)
{
if ( c == '\n')
break;
while(c != '\n')
{
while(counter < lim-1)
{
s[counter] = c;
counter++;
}
}
}
return 0;
}
SOLVED! - I think! I think I have finally figured it out. The inner loops as written in my redone solution will still loop endlessly or at lease till lim is reached. I added break
statements and think I am on my way to a solution.
I am still wrestling with how to run gdb on this problem though; enter the command line entries AND print the value of c. Linking gdb to the pid of the executable still did not work as expected. I even posted a separate question regarding gdb.
but to my surprise it happily soldiers on
You have three nested loops. A newline would terminate one of the inner loops, while the outermost loop would happily carry on (until you've hit Enter lim times).
I can give you a hint: you probably shouldn't be using nested loops for this.
You have added loops that didn't exist in the original ... that's conceptually and logically wrong. The most obvious solution uses break:
for (i = 0; i < lim-1; ++i)
{
c = getchar();
if (c == '\n')
break;
if (c == EOF)
break;
s[i] = c;
}
Or if you're pretending that C doesn't have break, you can do something like this (this is not exactly equivalent because i doesn't have the same value if '\n' or EOF is encountered):
for (i = 0; i < lim-1;)
{
c = getchar();
if (c == '\n')
i = lim-1;
else if (c == EOF)
i = lim-1;
else
s[i++] = c;
}
Or you can use the Pascal approach:
#include <stdbool.h>
...
i = 0;
bool more = i < lim-1;
while (more)
{
c = getchar();
if (c == '\n')
more = false;
else if (c == EOF)
more = false;
else
{
s[i++] = c;
more = i < lim-1;
}
}
With goto
i=0;
loop:
if( i >= lim - 1) goto end;
c = getchar();
if(c == '\n') goto end;
if(c == EOF) goto end;
s[i++] = c;
goto loop;
end:
Without break, goto and with just one for, still without && and ||.
for (i=0; i < lim - 1 ? ((c=getchar()) == '\n' | c == EOF) == 0 : 0; ++i)
s[i] = c;
Update
As noted by #Jim it's way better to set order of execution explicitly by using internal ?:
for (i=0; i >= lim - 1 ? 0 : (c=getchar()) == '\n' ? 0 : c != EOF; ++i)
s[i] = c;

Resources