My For loop counter is not increasing as expected - c

I'm trying to replace the jth value of the function's input string to '0' whenever the ith value of alphabet is contained in the function's input.
I am expecting this for-loop to increment i whenever the alphabet[i] equals input x[j] but it gets stuck at i when it does. What is going on here??
P.S This is an introductory programming course (CS50) and it uses different syntax then standard C.
void checkrepeat(string x)
{
string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int alphalen = strlen(alphabet);
for (int i = 0; i < alphalen; i++)
{
for (int j = 0; j < strlen(x); j++)
{
if (alphabet[i] == x[j])
{
x[j] = '0';
printf("%i,", i);
printf("%c,", alphabet[i]);
printf("%s\n", x);
}
}
}
}
The output of function with value x = 'AAA' gives me
0,A,0AA
0,A,00A
0,A,000
I am expecting it to give me
0,A,0AA
1,B,0AA
2,C,0AA

This is my first post so pardon me if I am too verbose or not following any unsaid rules; I would be happy to include any suggestions as I contribute more.
I could be wrong but looks like "Your expected output pattern" and "your interpretation of assignment" are contradictory.
Let me explain why ?
1 - Expected Output for x='AAA'
I am expecting it to give me
0,A,0AA
1,B,0AA
2,C,0AA
2 - your interpretation of assignment
replace the 'j'th value of the function's input string to '0' whenever the 'i'th value of alphabet is contained in the function's input.
Here you are interpreting whenever as "update input string with '0' for **ALL** matches"
i.e. replace all A's with 0's.
If I follow interpretation [2] then output of your function code "as is" for x='AAA' would print like this
0,A,0AA
0,A,00A
0,A,000
i loop with j=1 will run but nothing is printed because there is no B in input string
i loop with j=2 will run but nothing is printed because there is no C in input string
and this will continue till Z
and the loop will end
BTW - I hope you can see the waste of CPU processing power in your solution.
If your interpretation [2] is correct then your expectation of output [1] is erroneous and vice versa.
ASSUMING interpretation [2] is correct then you need to change your code as below however the output would be different from expected output [1].
void checkrepeat(char x[])
{
char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int alphalen = strlen(alphabet);
for (int i = 0; i < alphalen; i++)
{
for (int j = 0; j < strlen(x); j++)
{
if (alphabet[i] == x[j])
{
x[j] = '0';
}
}
printf("%i,", i);
printf("%c,", alphabet[i]);
printf("%s\n", x);
}
}
And output of your modified function for x='AAA' would print like this
0,A,000
1,B,000
2,C,000
...
25,Z,000
As an example when x='ABCDZABCDZ' then the expected output would look like
0,A,0BCDZ0BCDZ
1,B,00CDZ00CDZ
2,C,000DZ000DZ
3,D,0000Z0000Z
4,E,0000Z0000Z
...
25,Z,0000000000
Open this link to see Working code in C
https://onlinegdb.com/rJhda-gMP
3 - your interpretation of assignment
I am expecting this for-loop to increment the 'i' whenever the alphabet[i] equals input x[j]
Here you are interpreting whenever as "as soon as first match is found update input string with '0' and increment 'i'"
ASSUMING interpretation [3] is correct, following code changes are needed to print your expected output [1]
void checkrepeat(char x[])
{
char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int alphalen = strlen(alphabet);
for (int i = 0; i < alphalen; i++)
{
for (int j = 0; j < strlen(x); j++)
{
if (alphabet[i] == x[j])
{
x[j] = '0';
break;
}
}
printf("%i,", i);
printf("%c,", alphabet[i]);
printf("%s\n", x);
}
}
If I follow interpretation [3] then it meets the expected output [1] and for x='AAA' your function would print like this which
0,A,0AA
1,B,0AA
2,C,0AA
...
25,Z,0AA
As an example when x='ABCDZABCDZ' then the expected output would look like
0,A,0BCDZABCDZ
1,B,00CDZABCDZ
2,C,000DZABCDZ
3,D,0000ZABCDZ
4,E,0000ZABCDZ
...
25,Z,00000ABCDZ
Open this link to see Working code in C
https://onlinegdb.com/rJhda-gMP
Hope it helps.

Firstly, printf("%c,", alphabet[i]);is an error. You probably didn't mean to use the , after %c. Remove it.
Second,Its easy to loose the logic in nested loops, especially as a beginner. Write it down on paper and run through it, If you haven't yet learn about debuggers.
Now,you probably do not want i to ++ when there is a match between alphabet[i]and x[j], because i is your loop counter, and should not be messed with like that (You have likely confused a for loop with a while loop or are coming from something like Scratch).
I would suggest declaring a separate variable, say int x for this task.
As already mentioned in the comments, you haven't actually implemented this incrementation to take place(with a simple x++; in the if statement), and have wrongly assumed that somehow the i++ in your for loop has done it for you .
Again, I'll suggest you to hit the books and go back to see the exact workings of a for loop , which is very frequently used in C , so you cannot afford to be fuzzy on its key concepts.
Also, you seem to expect the string x to remain 0AA ... If this is the case , why would the first statement in you if() be x[j] = '0'; ? This will make every jth element of x that matches with alphabets a '0'.
Further, in the expected output, you have expected alphabet[i] to be A , then B , then C, despite clearly stating in your question that you had passed x as "AAA" (which obviously cannot then match with B or C).
Maybe you haven't written the 'I expect' with clear forethough. Please do not include sample expected output if it is not possible with the code you have supplied in the question. It confused me, and could confuse anyone. I assume you drastically shortened the code for S.O. but supplied the expected output of the original code you have somewehere on your computer.

Related

Mastermind game in C(with words)

I am probably not going to get help here because my question is far from being specific (I don't even know what exactly wrong with it) but, according to my professor's tests, there is something wrong with it (wrong in terms of correctness - it doesn't provide correct number of direct and indirect matches) (I have no access to his tests). As far as I have been testing, it passes all of my tests. However, there are over a couple hundred million possible outcomes (I think) and I can't test them all because I don't know how to do automated testing...
Here is my code that performs the "logic" part of the game called mastermind, which is compares a string of randomly generated letter (8 max) with user input string (a guess). I wanted to see if anyone has encountered this game in the past and knows the logic of how it supposed to compare two strings and generate the correct number of exact and inexact guesses.
// userInput->position - a length of a string(max 8)
// userInput->code - randomly generated code
// userInput->arr - user input string
void checkForExactMatch(Data* userInput) {
int i;
for (i = 0; i < userInput->position; i++) {
if (userInput->code[i] == userInput->arr[i]) {
userInput->exactMatch++;
userInput->arr[i] = 'a';
}
else
checkForInExactMatch(userInput, i);
}
}
void checkForInExactMatch(Data* userInput, int i) {
int j;
for (j = 0; j < userInput->position; j++) {
if (userInput->arr[j] == userInput->code[i]) {
userInput->arr[j] = 'a';
userInput->inExactMatch++;
break;
}
}
}
Looking over your code there were a couple of observations to be made. First in your for checkForExactMatch() the call to checkForInExactMatch is inside your for loop. So on the first mismatch you call checkForInExactMatch and when you return from checkForInExactMatch -- you call it again on the next iteration unless your first mismatch just happens to be on the final character.
To address that issue, you should fully determine whether you have an exact match or not, completing the for loop before checkForInExactMatch is called.
In your checkForInExactMatch, you have to decide whether a single common-character or some minimum length substring constitutes an inexact match.
It sounds like you have things worked out, and good job for pushing through to a solution. Depending on how you approached it, keeping a simple flag in checkForExactMatch()such as int matched = 1; and then loop turning your test around
for (i = 0; i < userInput->position; i++)
if (userInput->code[i] != userInput->arr[i]) {
matched = 0;
break;
}
Then it's just a simple test of
if (matched) {
userInput->exactMatch++;
userInput->arr[i] = 'a';
}
else
checkForInExactMatch(userInput, i);
So long as what you have done accomplishes something similar, you are fine. Let me know if you have further questions.

Why is my program not copying the contents of string a to string b? Instead it printing some garbage value

The task is to ask user from which character and till where he wants to create another string.
int main()
{
char a[]="Working with stirng is fun";
printf("%s",a);
int s,e,j=0;
scanf("%d%d",&s,&e);
char b[e-s+2];
for(int i=s-1;i<=e-1;i++){
a[j]=b[i];
j++;
}
a[j]='\0';
printf("%s",b);
}
for eg: if the user enters 4 and 7, the output should be "king".
You appear to be trying to copy a portion of a to b, but in fact are assigning to elements of a.
You have your assignment in the loop backwards. Your a[] variable is the source string and b[] is the destination, but your assignment is a[j]=b[i]; which assigns b[i] to a[j]. This is a Really Good Example, by the way, of why variable names like a and b are bad. Had you used variable names like big_string and sub_string you wouldn't have had this problem. Similarly, names like i and j when you have multiple strings are confusing--big_index and sub_index or some such would be far more clear.
Stylistically, you would do better to keep i and j more closely parallel, instead of declaring and increment i on the for line, and declaring and incrementing j entirely differently:
int i, j;
for (i = s - 1, j = 0 ; i <= e - 1 ; i++, j++)
b[j] = a[i];
b[j] = '\0';
seems much cleaner to me.
Better yet, in my opinion, would be to use a single variable to track the number of chars processed, and use it as an offset to the original string and the index to the substring:
start--; // adjust user's input to start at 0 instead of 1
end--;
int dex;
for (dex = 0 ; dex <= end - start ; dex++)
sub_string[dex] = orig_string[start + dex];
sub_string[dex] = '\0';
(I also changed to more clear variable names, and shifted the correction for indexing from 1 to 0 to the variables instead of doing math inside the loop which just adds confusion).
And finally, the easiest way of all to do this is to use the built-in strncpy() function:
strncpy(sub_string, &orig_string[start], end - start + 1);
Just change the line
a[i] = b[j];
to b[j]=a[i];
and a[i] = '\0';
to b[j]='\0';

C's For loop's arguments

I want to initialize an 16-cel-long array with 0, 1, 2 and 3 by blocks of four cels. So here is my first attempt at this:
int main(void) {
int t[16];
int i;
for (i = 0; i<=15; t[i++]=i/4)
{
printf("%d \n", t[i]);
}
return 0;
}
However, here is what I get. I know I can do it differently by just getting the affectation into the for loop, but why does this not work?
EDIT: Please do note that the printf only serves to check what the loop did put in the array.
The initialization works fine; you're just printing the cell before initializing it. Remember that the loop increment is done after each iteration. If you unroll the loop, you have:
i = 0; /* i is now 0 */
print(t[i]); /* prints t[0] */
t[i++] = i/4; /* sets t[0] */
/* i is now 1 */
print(t[i]); /* prints t[1] */
t[i++] = i/4; /* sets t[1] */
/* i is now 2 */
print(t[i]); /* prints t[1] */
/* etc. */
As well as the off-by-one errors with the loop begin/end that have been mentioned in other posts, this code:
t[i++]=i/4
causes undefined behaviour because i is read and written without a sequence point. "Undefined behaviour" means anything can happen: the value could be 3, or 4, or anything else, or the program could crash, etc.
See this thread for more in-depth discussion, and welcome to C..:)
I do not understand what you are trying to accomplish, but please let me show you a similar piece of code, first.
int main(void) {
int t[16];
int i;
//edited the code; providing standard way to do the task
for (i = 0; i<=15; i++)
{
t[i]=i/4;
printf("%d \n", t[i]);
}
return 0;
}
EDIT:
The while loop should be written that way:
int i = 0;
while (i<=15){
t[i] = i%4;
i++;
}
Which means set t[i] equal to i%4 and then increment i.
Since you are a beginner, I've updated the for loop and it now provides a standard way to do your task. It's better to have a simple increment on the third for loop command; do the rest of the job inside the for loop, as described above.
#naltipar: Yeah, I just forgot to initialize the first cel, just like grawity pointed out. Actually, the version I wrote for myself was with i++ but even then, since the third expression is executed after each loop, it sent out the same result. But whatever, it is fixed now.
However, I've got another problem which I'm sure I'm missing on but still can't figure it out:
int i = 0;
while (i<=15)
t[++i] = i%4;
This was first:
for(i = 0; i<=15; t[++i] = i%4);
but it resulted with an infinite loop. So in order to make sure that's not a problem specific to for, I switched to while andthe same thing still happens. That being said, it doesn't occur if i replace ++i by i++. I unrolled the whole loop and everything seems just fine...
I'm a beginner, by the way, in case you were wondering.
A clearer way to write this would be much less error-prone:
for (i = 0; i < 16; ++i)
printf ("%d\n", (t[i] = i % 4));
Personally I'd code something that way, but I'd never recommend it. Moreover, I don't really see much benefit in condensing statements like that, especially in the most important category: execution time. It is perhaps more difficult to optimize, so performance could actually degrade when compared to simply using:
for (i = 0; i < 16; ++i)
{
t[i] = i % 4;
printf ("%d\n", t[i]);
}
Even if it is you reading your own code, you make it difficult for your future self to understand. KISS (Keep It Simple, Stupid), and you'll find code is easier to write now and just as easy to modify later if you need to.

C - not entering if even when he should

I'm seriously mad right now. I need to compare one string with second, when chars from second string can somehow create first string. Example
foo1 = bill
foo2 = boril
foo2 can create foo1, because it contains all the letters from foo1.
So there's my program:
secret = religion
lettersGuessed = religonvpst
for(i = 0; i < lenSecret; i++){
for(l = 0; l < lenGuessed; l++)
printf("A: %c, B: %c, C: %d\n", secret[i], lettersGuessed[l], count);
if(secret[i] == lettersGuessed[l]){
printf("HI\n");
count++;
break;
}
printf("C: %d\n", count);
}
But variable count always stays at 0. This is output from console:
http://pastebin.com/YrHiNLNi
As you can see right from beginning, when secret[i] == lettersGuessed[l] in if should return true(1), it returns false(0). What's wrong with this? Why it's not working?
It's because you don't have curly braces after your second for loop. If you don't wrap the block of code you want to iterate over with curly braces, only the code before the first semi-colon encountered will be executed. In this case, your second loop will iterate over the printf statement but nothing else. So variable l will always be equal to lenGuessed when the if statement is executed and no letter from the first word matches the last letter of the second word, therefore count is never incremented.
Ok, this is totaly crazy.
Code that I posted in my question was of course wrong, because I forget braces of second for loop. Small, but fatal mistake, I know, but I was seriously mad so I didn't pay attention. Anyway, the original code is following:
int isWordGuessed(char secret[], char lettersGuessed[]){
int i, l, count = 0;
int lenSecret = strlen(secret);
int lenGuessed = strlen(lettersGuessed);
for(i = 0; i < lenSecret; i++)
for(l = 0; l < lenGuessed; l++)
if(secret[i] == lettersGuessed[l]){
count++;
break;
}
return lenSecret == count ? 1 : 0;
}
At first, it was returning 0. After compiling it with different tools and launching it on two different OS (Windows 7 64-bit and Windows XP 32-bit) i was finaly able to get 1 from that function.
It seems like variable count had non-zero value while launching, so instead of int i, l, count; I wrote int i, l, count = 0;
Well, now I don't understand only one thing - why sometimes variables has non-zero value even when I never touched them. It happened to my before, but only in C, in other languages I never had such a problem.

Prime numbers using Sieve of erastosthenes in C

I wrote the following program to display all prime numbers up to 150. It is not executing at all. what is so wrong with it?
# include <stdio.h>
int main(void)
{
int p[150], i, j;
for (i = 2; i < 150; i++)
p[i] = 0;
i = 2;
while (i < 150){
if (p[i] == 0)
printf("%i ", i);
for (j = 1; i*j <= 150; j++)
p[i*j] = 1;
i++;
}
return 0;
}
You're accessing p[i*j], which is beyond the valid [0-149] range. The condition i*j <= 150 will evaluate true when i*j is equal to 150, which is off-by-one. It should be i*j < 150.
The stdout stream is buffered. You need to flush at the end of your loop. Try adding a fflush(stdout).
Might be of less importance, but if you care about the resulting array (e.g.: wants to use it later), the value of p[2] is erroneously set to 1. However, your program would still print 2, but that's because your loop prints numbers before changing the value of p[i*j]. Concluding, numbers get printed correctly, but the values in the array are not entirely correct.
i*j <= 150 is incorrect, it should be i*j < 150, because the p array has elements from 0 to 149. The program gets stuck in an infinite loop because of this.
EDIT: The rest of this answer was incorrect, so I've removed it.
As a learning exeercise, try adding some printf's to learn what your program does.
Also bear in mind that, as jweyrich says, that printf without \n in it will not output anything until (possibly) the program exits.

Resources