Checking if Char contains numbers and converting it to INT - c

Well there is program doing it's function right, but I am trying to make it check, if user-entered value is number(doesn't contain letters or signs). So basically I am using if with isdigit or '/0' condition. Program compiles properly, but I am getting error, when entering less than 3 types(even numbers...). What is wrong with it? Only thing I need is to skip loop when number is 0-999 and re-ask while it isn't, or if it is not number.
char x[5];
bool isgood;
int tab[20][2],i=0,a;
do
{
isgood = TRUE;
printf("Write a where 0<a<1000\n");
scanf("%4s", x);
for (int j = 0; j < 4; j++)
{
if (isdigit(x[j])==0 || x[j]!='/0') isgood = FALSE;
}
a = atoi(x);
if (a<1000 && isgood == TRUE) break;
} while (1);

Wrong:
Your boolean-logic
Your null-character
Calling atoi when isgood is FALSE
Change this:
isdigit(x[j])==0 || x[j]!='/0'
To this:
isdigit(x[j])==0 && x[j]!='\0'
And this:
a = atoi(x);
if (a<1000 && isgood == TRUE) break;
To this:
if (isgood == TRUE)
{
a = atoi(x);
if (0<a && a<1000)
break;
}
Here is a far more simple way of doing the whole thing:
int x;
char c;
do
{
printf("Write a where 0<a<1000\n");
if (scanf("%d",&x) == 0)
scanf("%c",&c);
else if (0<x && x<1000)
break;
}
while (1);

Related

Code no longer providing any output in terminal

I have been working on a hangman game for my class which is due today and just now it decided to no longer provide any output from my code. If someone could please give it a look so I can go back to possibly submitting this assignment, I would be very appreciative. I dont know what changed specifically.
char **readWordList(char *, int *);
int main(int argc, char *argv[]) {
char **wordList;
char inputFile[100];
int count = 0;
int i;
if (argc != 2) {
printf("You need to provide the word list file name.\n ");
printf("Usage: $0 filename\n");
return -1;
}
wordList = readWordList(argv[1], &count); //function (target input[s], y placeholder var)
if (wordList == NULL) {
printf("Read word failed\n");
exit(1);
}
printf("fortnite");
int a = 0; //placeholder variables
int b = 0;
int c = 0;
int v = 0;
int g = 0;
int hit = 0;
srand(time(NULL)); //random variable for word selection
int r = rand() % 3;
int chances = 10;
char *word = wordList[r]; //address word from line.txt
char guess;
char misses[10];
int lettercount = 0;
//make blank variable by reading random accessed word
for (size_t a = 0; word[a] != 0; a++) {
lettercount++;
}
char space[lettercount];
// write underscores in place of spaces in temporary array
for (size_t c = 0; word[c] != '\0'; c++) {
space[c] = 95;
}
char blank[lettercount * 2]; //equal to array size empty array
// borrowing my spacename function, but seems to make artifacts in blank input now
int t = 0;
int k = 0;
while (space[t] != '\0') {
k = 2 * t;
if (k > lettercount * 2 - 2) {
blank[k] = space[t];
break;
}
blank[k] = space[t];
blank[k + 1] = ' ';
}
while (chances > 0) {
printf("Chances:%d\n", chances);
printf("Misses:%d\n", misses);
printf("Word:%s\n", blank);
printf("Guess[Q]:");
scanf("%c\n", &guess);
while (word[b] != '\0') {
if (guess = 'Q') {
exit(0);
}
if (guess = word[b]) {
v = b * 2;
blank[v] = guess;
b++;
hit = 1;
}
b++;
}
if (hit != 1) {
misses[g] = guess;
}
if (hit = 1) {
hit = 0;
}
chances--;
g++;
}
}
There are multiple problems in the code, including some serious ones:
the #include lines are missing.
the readWordList function is missing.
if (guess = 'Q') sets guess to 'Q' and evaluates to true. You should write if (guess == 'Q')
if (guess = word[b])... same problem.
printf("Misses:%d\n", misses); should be printf("Misses:%s\n", misses); and misses should be initialized as the empty string.
printf("Word:%s\n", blank); has undefined behavior as blank is not null terminated.
while (space[t] != '\0') may iterate too far as space does not have a null terminator since it's length is lettercount and all elements have been set to 95 ('_' in ASCII). Yet since you never increment t, you actually have an infinite loop. Use a simple for loop instead: for (t = 0; i < lettercount; t++)
scanf("%c\n", &guess); reads a character and consumes any subsequent white space, so the user will have to type another non space character and a newline for scanf() to return. You should instead use scanf(" %c", &guess);
while (word[b] != '\0') will iterate beyond the end of the array after the first guess because you do not reset b to 0 before this loop. Furthermore, b is incremented twice in case of a hit. You should use for loops to avoid such silly mistakes.
if (hit = 1) { hit = 0; }... the test is incorrect (it should use ==) and you could just write hit = 0; or better set hit to 0 before the inner loop.
inputFile is unused.
You should compile with gcc -Wall -Wextra -Werror to avoid such silly bugs that can waste precious time.
i fixed it, i lost a variable which provided the chance that a while loop would end for the spacing array function
sorry for being annoying

How do I store an array in three different ones based on delimiters

I want to split an input array into three different ones based on a / as a delimiter.
I have tried the (probably the naive) approach of storing an input string into different arrays by using getchar and while to read in the characters into an array and using a counter to count how many times a / appears.
Based on this number I would use:
if (slashcounter == 0) {
destinationarray[i++] = c;
}
to store it into the proper array. full implementation below.
please note that I try to do this using only stdio.h
#include <stdio.h>
char c;
char replace[80], toBeReplaced[80], input[80], testInput[80];
int i = 0;
int slashcounter = 0;
int main(){
puts("Enter a line of text: ");
while (( c = getchar()) != '\n'){
if (c == '/') {
slashcounter++;
}
if (slashcounter == 0) {
replace[i++] = c;
}
else if (slashcounter == 1) {
toBeReplaced[i++] = c;
}
else if (slashcounter == 2) {
input[i++] = c;
}
}
//debug purpose
puts("The arrays have the following content\n");
puts("replace[]:\n");
puts(replace);
puts("\n");
puts("toBeReplaced[]:\n");
puts(toBeReplaced);
puts("\n");
puts("input[]:\n");
puts(input);
printf("Slashcounter = %d\n",slashcounter);
return 0;
Unfortunately, what happens is: that the first word i.e. the word before the first slash is stored correctly but the other two are empty.
What have I done wrong here
the current output with the input this/test/fails
Enter a line of text:
this/test/fails
The arrays have the following content
replace[]:
this
toBeReplaced[]:
input[]:
Slashcounter = 2
Program ended with exit code: 0
p.s. I would also like to ensure that the /s are not in the output array.
Thank you for your help.
You have two immediate problems in your code, first you miss to add a null character to end each sub string, second you never reset the index to 0 when you read a /
Other problems are you do not check if you will write out of the arrays, and you do not not manages the EOF
You also test the value of slashcounter all the time, this is quite expensive for nothing, you can have 3 loops or use a pointer to point to the array to fill etc
There is also no reason to use global variables, all of them can be local in main
Example with minimal changes :
#include <stdio.h>
int main(){
int c;
char replace[80], toBeReplaced[80], input[80];
int i = 0;
int slashcounter = 0;
puts("Enter a line of text: ");
while (( c = getchar()) != '\n') {
if (c == EOF) {
fprintf(stderr, "unexpected EOF");
return -1;
}
if (c == '/') {
if (slashcounter == 0) {
replace[i] = 0;
}
else if (slashcounter == 1) {
toBeReplaced[i] = 0;
}
else if (slashcounter == 2) {
input[i] = c;
}
i = 0;
slashcounter++;
}
else if (slashcounter == 0) {
if (i != (sizeof(replace) - 2))
replace[i++] = c;
}
else if (slashcounter == 1) {
if (i != (sizeof(toBeReplaced) - 2))
toBeReplaced[i++] = c;
}
else if (slashcounter == 2) {
if (i != (sizeof(input) - 2))
input[i++] = c;
}
}
if (slashcounter == 0) {
replace[i] = 0;
toBeReplaced[0] = 0;
input[0] = 0;
}
else if (slashcounter == 1) {
toBeReplaced[i] = 0;
input[0] = 0;
}
else if (slashcounter == 2) {
input[i] = 0;
}
//debug purpose
puts("The arrays have the following content\n");
puts("replace[]:\n");
puts(replace);
puts("\n");
puts("toBeReplaced[]:\n");
puts(toBeReplaced);
puts("\n");
puts("input[]:\n");
puts(input);
printf("Slashcounter = %d\n",slashcounter);
return 0;
}
Note I use an int for c to handle EOF and I removed the useless array testInput
Compilation and execution :
pi#raspberrypi:/tmp $ gcc -pedantic -Wall -Wextra s.c
pi#raspberrypi:/tmp $ ./a.out
Enter a line of text:
this/test/fails
The arrays have the following content
replace[]:
this
toBeReplaced[]:
test
input[]:
fails
Slashcounter = 2

How do I check if a string only contains one and zero?

I am trying to detect whether a string contains only the characters '0' and '1'. This is what I have so far:
while (indexCheck < 32) {
if ((input[indexCheck] != '0') && (input[indexCheck] != '1')) {
printf("not binary ");
indexCheck++;
} else if ((input[indexCheck] = '0') && (input[indexCheck] = '1')) {
indexCheck++;
printf("is binary ");
}
}
I know why it returns "is binary" or "not binary" for every single character in the array, but I don't know how to fix this. I want it to return "is binary" once if the string is only made of '1' and '0', and the opposite if this is false. I'm new to C so all help is appreciated.
Instead of looping manually through the string, you can see if it only contains certain characters by checking to see if strspn() returns the length of the string (By seeing if the index of the value it returns is the 0 terminator at the end of the string):
_Bool is_binary(const char *s) {
if (!s || !*s) {
return 0;
}
return s[strspn(s, "01")] == '\0';
}
I would make a function for this:
int isBinary(const char *input)
{
for (int i = 0; input[i]; ++i)
if (input[i] != '0' && input[i] != '1')
return 0;
return 1;
}
Then you can call the function:
if (isBinary("0001110110101"))
printf("is binary\n");
else
printf("is not binary\n");
https://ideone.com/tKBCbf
You can stop looping through the string the moment you find a character which is neither '0' nor '1'. After the loop is terminated, you check whether or not you've reached the end of the string, i.e. the current character is a null character '\0'
while (*s == '0' || *s == '1') ++s;
if (*s)
puts("not binary");
else
puts("binary");
You can do:
while (indexCheck < 32)
{
if ((input[indexCheck] != '0') && (input[indexCheck] != '1'))
{
break;
}
else
{
indexCheck++;
}
}
if (indexCheck == 32)
printf("is binary ");
else
printf("is not binary ");
Only when it has processed all elements and did not encounter a non 1-or-0 ends the loop with indexCheck == 32 so you can use that to determine what to print.
Note also that your else condition is not needed.
there is a block of code for you with comments.
#include <stdio.h>
#include <stdlib.h>
#define STRING_SIZE 32 // Better to use #define for reusability
// Function prototype
int isBinary(char * testInput);
// Main program
int main(void)
{
// Test inputs
char testInputBinary[33] = "01010101010101010101010101010101";
char testInputNotBinary[33] = "010101010101010101010101010101ab";
// Test & collect results
if (isBinary(testInputBinary))
{
printf("Binary ! \n");
}
else
{
printf("Not binary ! \n");
}
if (isBinary(testInputNotBinary))
{
printf("Binary ! \n");
}
else
{
printf("Not binary ! \n");
}
return EXIT_SUCCESS;
}
int isBinary(char * testInput)
{
int loopIdx = 0; // Loop index
int returnVal = 0; // 0: False, 1: True
// iterate over string
for (loopIdx = 0; loopIdx < STRING_SIZE; loopIdx++)
{
if(testInput[loopIdx] != '0' && testInput[loopIdx] != '1')
{
break;
}
}
// If the loop is not broken, it means all characters are in binary form
if (loopIdx == STRING_SIZE)
{
returnVal = 1;
} // No need to writing else clause since returnVal = 0 at the beginning
return returnVal;
}
int isBinary = 1;
while (input[indexCheck] != '\0')
{
if (input[indexCheck] != '1' && input[indexCheck] != '0')
{
isBinary = 0;
break;
}
++indexCheck;
}
if (isBinary)
{
printf("binary");
}
else
{
printf("not binary");
}
Check each element in string input. If input[index] is not 0 or 1 the flag isBinary becomes 0 and breaks while. And you do not need length of string.

How can I make sure that there is no limit to how long a password can be?

I wrote a code in C where the user has to have a "$", a number and a capital number in their password for it to be valid, but I'm confused as to what to do so that the password can be as long as they want, without me having to write char password[100000000000]or something like that.
int something = 100;
char password[something];
int index = 0;
int x = 0;
int y = 0;
int z = 0;
printf("Enter Password: "); //Mike$4
scanf("%s", password);
do{ // If index is strlen, then we checked every char of pw
// Ex. Password is length 6, then index 0 - 5 will be checked
if(index == strlen(password) && x>0 && y>0 && z>0){
printf("Good password!");
break;
}
if(index == strlen(password) && (x==0 || y==0 || z==0)){
printf("BAD PASSWORD");
break;
}
if(isupper(password[index]) || isdigit(password[index]) ||
password[index] == '$'){
if(isupper(password[index])){
x++; index++;
continue;}
if(isdigit(password[index])){
y++; index++;
continue;}
if(password[index] == '$'){
z++; index++;
continue;}
}else{index++;
continue;
}
}while(index <= strlen(password));
This is my code. Thanks!
If you truly want unlimited length (although its utility is somewhat questionable -- it's probably better to just pick a big limit and be done with it), you're going to have to ditch scanf for something like fgets that allows you to specify how many characters to read, then read the input in chunks. You'll probably want to use an easy-to-grow structure (like a linked list of slightly-less-than-page-sized string buffers) to read in these chunks, then allocate a buffer for the final string once you hit a newline (or EOF, depending on your desired semantics) in your input.
The simplest way would be to use fgets. Note that scanf("%s") will only get a single word and some passwords might have spaces. But, the real reason to use fgets is that you can prevent overflow as in:
char password[1000];
fgets(password,sizeof(password),stdin);
char *cp = strchr(password,'\n');
if (cp != NULL)
*cp = 0;
That's the simplest solution.
But, if you really need a large password [of unspecified length], you can grow the password variable from realloc, just as would be done for a dynamic array:
char *password = NULL;
int pwmax = 0;
int pwlen = 0;
void *
xrealloc(void *ptr,size_t len)
{
void *tmp;
tmp = realloc(ptr,len);
if (tmp == NULL) {
free(ptr);
exit(1);
}
return ptr;
}
while (1) {
int chr = fgetc(stdin);
if (chr == EOF)
break;
if (chr == '\n')
break;
if (pwlen >= pwmax) {
if (pwlen >= 1000000) {
fprintf(stderr,"password beyond reasonable max limit\n")
exit(1);
}
pwmax += 100;
password = xrealloc(password,pwmax);
}
password[pwlen++] = chr;
}
password = xrealloc(password,pwlen + 1);
password[pwlen] = 0;
Simply process one character of the password at a time; there is no need to have it all in memory at once.
#include <ctype.h>
#include <stdio.h>
#include <stdbool.h>
int main(void)
{
printf("Enter password: ");
bool SawDollar = false;
bool SawDigit = false;
bool SawUpper = false;
while (1)
{
int c = getchar();
if (c == EOF || isspace(c))
break;
if (c == '$')
SawDollar = true;
else if (isdigit(c))
SawDigit = true;
else if (isupper(c))
SawUpper = true;
}
if (SawDollar && SawDigit && SawUpper)
printf("Good password!\n");
else
printf("Bad password.\n");
}

functions only returning 1?

I'm having an issue where my functions seems to be only returning one. I thought that I was returning the functions correctly but it seems that I am not.
char goAgain()
{
char ch;
do
{
printf("Would you like to go again? ");
ch = getchar();
while(fgetc(stdin) != '\n');
}while(ch != 'n' || 'y');
return ch;
}
double findMedian(int array[], int length)
{
int mid;
double median, medianLeft, medianRight;
if(length % 2 == 0)
{
mid = length / 2;
// medianLeft = array[mid];
// medianRight = array[mid + 1];
}
else
{
mid = length / 2;
median = array[mid];
}
return median;
}
this is how I am calling the median
double mean = findMedian(array, length);
why is it only giving me a one in my return. also when i try to repeat the goAgain I don't get the correct ch to be returned either.
option = goAgain();
things are a lot different in the c world compared to the java world.
do
{
int num = menu();
if(num == 1)
fillArray(array, size);
else if(num == 2)
{
int newSize = readNum();
fillArray(array, newSize);
}
else if(num == 3)
{
int length = size;
sortArray(array);
double mean = findMean(array, length);
double median = findMedian(array, length);
printResults(mean, median);
}
else
{
printf("Please enter a valid number\n");
num = menu();
}
option = goAgain();
}while(option == 'y');
This condition:
(ch != 'n' || 'y')
Is probably not doing what you want. It is interpreted by the compiler like this:
((ch != 'n') || 'y')
Which means "if ch is not the character n OR if the character y". If your machine uses ASCII, then y has the value 121. What happens if you do:
((whatever) || 121)
For the boolean OR operator (||) the value 0 represents false and every other value represents true. And what do you get when at least least of the operands of a boolean OR operation are true? You get true.
So, your condition is, essentially, the same as simply writing
(1)
It looks like you want:
(ch != 'n' && ch != 'y');
When this:
if(length % 2 == 0)
... evaluates true, you don't calculate a value for median, yet still return it.
(And then add in whatever becomes from Carl's answer, which is dealing with the "and also" part of your question!)

Resources