I am new to C and trying to Write a program that reads in a series of integers until a value of zero is encountered and then prints the sum of all the numbers except those that are equal to 13 or that come immediately after a 13. It is guaranteed that there is at least one zero in the input.
At most 100 lines of input, each line containing a single integer. At least one of the lines will contain the integer 0.
My code is like this:
#include <stdio.h>
int main ()
{
int sum = 0;
int data[100];
int i = 0;
scanf("%d\n", &data[i]);
while (data[i] != 0 && i < 100) {
if (data[i] == 13) {
sum = sum;
} else if (i > 0 && data[i-1] == 13) {
sum = sum;
} else {
sum += data[i];
i++;
}
scanf("%d\n", &data[i]);
}
printf("%d",sum);
}
I tried to get rid of the number after 13 but failed... Please help.
You could also try this:
// extra flag outside loop
int found13 = 0;
while (data[i] != 0 && i < 100) {
if (data[i] == 13) {
found13 = 1; // set flag
} else if (found13) {
found13 = 0; // clear flag
} else {
sum += data[i];
i++;
}
scanf("%d\n", &data[i]);
}
Improvements:
Doesn't peek back at the previous element
Doesn't need to constantly check i > 0):
EDIT: further refactor
int sum = 0;
int found13 = 0;
int data;
while (scanf("%d\n", &data) == 1 && data != 0) {
if (data == 13) {
found13 = 1; // set flag
} else if (found13) {
found13 = 0; // clear flag
} else {
sum += data;
}
}
Improvements:
As #PaulOgilvie pointed out, you no longer need an array to store your results
... neither do you need i
... nor the extra call to scanf outside the loop
Now works for any number of inputs
It is easiest to collect all conditions in one boolean expression of the if-statement:
if (data[i] != 13 && (i == 0 || data[i-1] != 13){
sum += data[i];
}
i++;
... and move i outside the if body.
Related
Here is the code:
#include <stdio.h> // printf
#include <cs50.h> // get_long
#include <string.h> // strlen
#include <stdlib.h> // stdlib
int credit_test(string input);
int main(void)
{
string userInput;
// Gets user input, and tests if input is valid
bool isInvalid = false;
do
{
userInput = get_string("Number: "); // Prompts user for input
for(int i = 0, evenIndex = strlen(userInput); evenIndex > i; i++)
{
if(userInput[i] - 48 >= 0 && userInput[i] - 48 <= 9 && (strlen(userInput) == 15 || strlen(userInput) == 16)) // Tests if input is valod
{
isInvalid = false;
}
else
{
isInvalid = true;
break;
}
}
}
while(isInvalid);
int keyValidity = credit_test(userInput);
}
int credit_test(string input)
{
int inputLen;
inputLen = strlen(input);
// Even number calculation
int evenArr[16];
int evenSum = 0;
int evenIndex = 0;
printf("Length: %i\n", inputLen);
for(int i = 0; inputLen > i; i++)
{
int n = i * 2;
evenArr[evenIndex] = input[n] * 2;
if(evenArr[evenIndex] > 0)
{
evenArr[evenIndex] -= 96;
}
if(evenArr[evenIndex] > 9) // Code to split doubles
{
int doubleNum = evenArr[evenIndex];
evenArr[evenIndex] = 1;
evenIndex++;
evenArr[evenIndex] = doubleNum % 10;
}
evenIndex++;
evenSum += evenArr[i];
printf("%i\n", evenArr[i]);
printf("Length: %i\n", inputLen);
}
printf("Length: %i\n", inputLen);
printf("Even Sum: %i\n", evenSum);
// Odd number calculation
int oddArr[16];
int oddSum = 0;
int oddIndex = 1;
for(int i = 0; 16 > i; i++)
{
oddArr[i] = input[oddIndex];
if(oddArr[i] > 0)
{
oddArr[i] -= 48;
}
oddSum += oddArr[i];
oddIndex += 2;
printf("%i\n", oddArr[i]);
}
printf("Odd Sum: %i\n", oddSum);
// Validity test
int finalSum = evenSum + oddSum;
int cardType = finalSum % 10;
printf("Final Sum: %i\n", finalSum);
if(cardType == 0 && (input[0] - 48) == 5)
{
printf("MasterCard \n");
}else if (cardType == 0 && (input[0] - 48) == 4)
{
printf("Visa \n");
}else if(cardType == 0 && (input[0] - 48) == 3)
{
printf("Amex \n");
}else
{
printf("Invalid \n");
}
return 0;
}
I just cannot wrap my head around why, but if you run the code, and keep an eye on the "inputLen" variable it stays what it should be, but in the first for loop which gets the even number in the input, the inputLen stays the same, which is correct, but when the loop finishes, for some reason, the variable changes to 0? So would anyone mind to explain as to why its happening? And sorry if the code is all wonky and bad :)
Thanks so much.
This part of the loop
for(int i = 0; inputLen > i; i++)
{
int n = i * 2;
evenArr[evenIndex] = input[n] * 2;
//...
invokes undefined behavior because the expression input[n] can access memory beyond the used array due to using the expression i * 2 as an index. For example then i is equal to inputLen - 1 then n will bi initialized by the expression 2 * ( inputLen - 1 ) and the value of the expression you are using as an index to access elements of the array input but the array does not have so many elements.
Also in this code snippet
if(evenArr[evenIndex] > 9) // Code to split doubles
{
int doubleNum = evenArr[evenIndex];
evenArr[evenIndex] = 1;
evenIndex++;
evenArr[evenIndex] = doubleNum % 10;
}
evenIndex++;
the variable evenIndex can be incremented twice that again can be a reason of undefined behavior when this variable is used as an index to access elements of the array evenArr.
I am trying to code minesweeper in C. I started out with assigning the values to a 2D array then print it. I tried everything but it didn't work.
This happens in my sample output:
The code is:
#include <stdio.h>
#include <stdlib.h>
struct Tile {
unsigned char isMine : 1;
char status;
};
int main() {
struct Tile arr[9][9];
unsigned char i;
unsigned char c;
unsigned char count = 10;
srand((unsigned)time(0));
for (i = 0; i < 9; i++) {
for (c = 0; i < 9; i++) {
if(rand() % 81 + 1 < count && arr[i][c].isMine == 0 && count > 0) {
arr[i][c].isMine = 1;
arr[i][c].status = 'X';
count--;
} else if (arr[i][c].isMine == 0) {
arr[i][c].status = '.';
}
}
if (count == 0) {
break;
} else {
continue;
}
}
for (i = 0; i < 9; i++) {
for (c = 0; c < 9; c++) {
printf("%c", arr[i][c].status);
}
printf("\n");
}
return 0;
}
Please help.
You never visit any fields in your loops except the 1st column due to incorrect loop header:
for (i = 0; i < 9; i++) {
for (c = 0; i < 9; i++) {
if(rand() % 81 + 1 < count && arr[i][c].isMine == 0 && count > 0) {
arr[i][c].isMine = 1;
arr[i][c].status = 'X';
count--;
} else if (arr[i][c].isMine == 0) {
arr[i][c].status = '.';
}
}
if (count == 0) {
break;
} else {
continue;
}
}
This will leave all other fields uninitialized and when you try to print it, strange things may appear.
Also as you only visit each field once (or at least that seems to be your intention), there is no need to check isMine at all. If you initialize properly, it must be 0 anyway.
Which of course requires that you intitialize properly as already mentioned in David's answer.
The condition can be reduced a bit more as the first part (..+1<count) already implies that count>0. No need to check again.
Finally, continue as last instruction of a loop is not really useful.
Your code could look like this:
struct Tile arr[9][9] = {{0}};;
...
for (i = 0; i < 9; i++) {
for (c = 0; c < 9; c++) {
if(rand() % 81 + 1 < count) {
arr[i][c].isMine = 1;
arr[i][c].status = 'X';
count--;
} else {
arr[i][c].status = '.';
}
}
if (count == 0) {
break;
}
}
Initialize the array:
struct Tile arr[9][9] = {{0}};
otherwise you read an uninitialized value (leading to undefined behaviour) in:
} else if (arr[i][c].isMine == 0) {
arr[i][c].status = '.';
}
Gets stuck inside of the valid = 0 while loop where it does not get passed scanf and keeps asking for input. The program was designed to accept an integer value for the GPA and then calculate the frequency of each gpa among what had been given.
#include <stdio.h>
int main(void) {
int amount, i, count, valid;
int GPA[200], GPAFreq[4];
valid = 0;
i = 1;
count = 1;
GPA[1] = 0; GPA[6] = 0;
GPA[2] = 0; GPA[7] = 0;
GPA[3] = 0; GPA[8] = 0;
GPA[4] = 0; GPA[9] = 0;
GPA[5] = 0; GPA[10] = 0;
GPAFreq[1] = 0; GPAFreq[3] = 0;
GPAFreq[2] = 0; GPAFreq[4] = 0;
printf("Enter the number of students: ");
scanf("%d", &amount);
while ( i < (amount + 1))
{
i += 1;
while (valid == 0)
{
printf("%d", GPA[i]);
if ( (GPA[i] == 4) || (GPA[i] == 3) || (GPA[i] == 2) || (GPA[i] == 1) )
{
valid = 1;
}
else
{
printf("GPA of student # %d is: ", i);
scanf("%d", &GPA[i]);
}
}
count = 1;
while (count < 5)
{
if (GPA[i] == count)
{
GPAFreq[count] +=1;
}
}
}
count = 1;
while (count < 5)
{
printf("\nGPA %d --- %d student(s).", count, GPAFreq[count]);
count += 1;
}
return 0;
}
When I execute this it does not get stuck on the while(valid == 0) loop, it gets stuck in the 1st while(count < 5) because you do not increment count inside this loop.
There are a few other things that pop out immediately to me in this code that I might as well point out.
You can automatically have all elements of an array set to 0 by declaring like int array[10] = {0}. There are a few ways of doing this (including for loops), but you don't need to manually type each one out like you do in lines 11-18
Arrays are 0 indexed in c, so you start counting from 0, not 1
You increment i at the beginning of the while loop (line 26) before it is accessed. Thus meaning the first index actually being used is 2 (remember it should be 0)
If you are limiting your number of students to 200, you should make sure the user doesn't enter in a number larger than this.
EDIT:
You will also need to reset valid to 0 before the while(valid == 0) loop (you could also just do while(!valid) btw)
This is my first question on this forum and it is rather tricky.
I am working on a problem in C where you are entering characters,until you enter the sign !. Then you have to extract the numbers and print their sum.
The input is in the format :
adasdas12fef 1 asdasdas43 da3 23adead
The output should be : 82 ( 12+1+43+3+23)
Note: The usage of string is forbidden.
I am sorry for the bad language.
If there are any questions about other details or usages, feel free to comment.
I think this will work for you :
#include <stdio.h>
int main(void) {
// declear and initialize the variables
char input[200];
char c;
int i = 0, j = 0, sum = 0, num = 0, next = 0;
// get input until '!' is pressed
while((c=fgetc(stdin)) != '!') {
input[i] = c;
i++;
}
// end string
input[i] = '\0';
// loop through the string
// if numeric found, will add to sum.
// for 2 numeric (one after another) will multiply
// previous one with 10 and add with the current one
for (j = 0; j < i; j++) {
if (next == 1) {
next = 0;
num = input[j-1] - '0';
num *= 10;
num += (input[j] - '0');
sum += num;
continue;
}
if (input[j] >= '0' && input[j] <= '9') {
if (input[j+1] >= '0' && input[j+1] <= '9') {
next = 1;
} else {
sum += (input[j] - '0');
}
}
}
printf("sum: %d\n", sum);
}
Please do not ask for full code. I found the problem interesting, that's why I did it. Try first, then ask if you face any specific problem.
How about some pseudo code to get you started?
state = spaces
number = 0
Forever {
Get ch
if (ch == EOF or `!`) {
if (state == num) print number
break;
}
if (state == space) {
if (ch is a digit) {
number = digit
state = num
}
} else {
if (ch is a digit) {
number = number * 10 + digit
} else if (ch is a space) {
print number
state = space
number = 0
}
}
}
i'm newbie in C programming .
i have written this code for adding two numbers with 100 digits , but i don't know why the code does not work correctly , it suppose to move the carry but it doesn't .
and the other problem is its just ignoring the first digit (most significant digit) .
can anybody help me please ?
#include <stdio.h>
#include <ctype.h>
int sum[101] = {0};
int add(int a, int b);
void main()
{
static int a[100];
static int b[100];
char ch;
int i = 0;
int t;
for (t = 0; t != 100; ++t)
{
a[t] = 0;
}
for (t = 0; t != 100; ++t)
{
b[t] = 0;
}
do
{
ch = fgetc(stdin);
if ( isdigit(ch) )
{
a[i] = ch - 48;
++i;
}
else
break;
}
while (ch != '\n' || i == 100 || i != '\0');
i = 0;
do
{
ch = fgetc(stdin);
if ( isdigit(ch) )
{
b[i] = ch - 48;
++i;
}
else
break;
}
while (ch != '\n' || i == 100 || i != '\0');
for (;i!=0; --i)
{
add(a[i], b[i]);
}
for (i==0;i != 101; ++i)
{
printf("%d", sum[i]);
}
}
int add( int a , int b)
{
static int carry = 0;
float s = 0;
static int p = 101;
if (0 <= a+b+carry <= 9)
{
sum[p] = (a + b + carry);
carry = 0;
--p;
return 0;
}
else
{
if (10 <= a+b+carry < 20)
{
s = (((a+b+carry)/10.0 ) - 1) * 10 ;
carry = ((a+b+carry)/10.0) - (s/10);
}
else
{
s = (((a+b+carry)/10 ) - 2) * 10;
carry = ((a+b+carry)/10.0) - (s/10);
}
sum[p] = s;
--p;
return 0;
}
}
Your input loops have serious problem. Also you use i to count the length of both a and b, but you don't store the length of a. So if they type two numbers that are not equal length then you will get strange results.
The losing of the first digit is because of the loop:
for (;i!=0; --i)
This will execute for values i, i-1, i-2, ..., 1. It never executes with i == 0. The order of operations at the end of each iteration of a for loop is:
apply the third condition --i
test the second condition i != 0
if test succeeded, enter loop body
Here is some fixed up code:
int a_len;
for (a_len = 0; a_len != 100; ++a_len)
{
int ch = fgetc(stdin); // IMPORTANT: int, not char
if ( ch == '\n' || ch == EOF )
break;
a[a_len] = ch;
}
Similarly for b. In fact it would be a smart idea to make this code be a function, instead of copy-pasting it and changing a to b.
Once the input is complete, then you could write:
if ( a_len != b_len )
{
fprintf(stderr, "My program doesn't support numbers of different length yet\n");
exit(EXIT_FAILURE);
}
for (int i = a_len - 1; i >= 0; --i)
{
add(a[i], b[i]);
}
Moving onto the add function there are more serious problems here:
It's not even possible to hit the case of sum being 20
Do not use floating point, it introduces inaccuracies. Instead, doing s = a+b+carry - 10; carry = 1; achieves what you want.
You write out of bounds of sum: an array of size [101] has valid indices 0 through 100. But p starts at 101.
NB. The way that large-number code normally tackles the problems of different size input, and some other problems, is to have a[0] be the least-significant digit; then you can just expand into the unused places as far as you need to go when you are adding or multiplying.