functions only returning 1? - c

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!)

Related

Error in my string passing into the function which is a pointer in C?

Instruction: Alright, I am working on a code where I am doing number conversions. I am prompting the user to give me a base and an input of bits with a mathematic symbol such as '+', '-', '*' etc, and I do the calculation, if you have a strategy for that, then feel free to give me an idea.
Problem: Regardless, I am working on some strategy on how to do it, but I am having trouble with my character, strings, char pointers. I don't know how to resolve it. I hardly understand what pointers are, besides a location in memory. I need help resolving this problem.
baseToDec Function: Anyways, I have a method/function called baseToDec, where I perform a conversion from bits to a decimal and return an int. Inside those parameters, I have a char* which takes in the value. such as '1001' which is the value 9.
Ways: However, when I put in the string "first" inside that parameter down in my main, I get a fault segmentation. I don't know how to declare that string value where I won't get warnings or a segmentation fault. I've tried changing the variable to be a char *first, I tried to do the address. I don't understand it. I would like to know how I can do it so I don't get a warning and it returns an integer smoothly.
int baseToDec(int base, char* value)
{
int len = strlen(value);
int power = 1, result = 0,i, j, num;
if(base > 2) //not binary
{
for (i = len - 1; i >= 0; i--)
{
result += number(value[i]) * power;
power = power * base;
}
}
else if(base = 2)
{
while(value[i] == '0' || value[i] == '1' )// (2) remove the most significant binary digit(leftmost) and add it to the result.
{
if(value[i] == '1')
{
result = result * 2 + 1;
}
else if(value[i] == '0')
{
result *= 2;
}
i++;
} // (3) If all binary digits have been removed, you're done. Stop.
}
return result;
}
int main()
{
int base, i = 0, j =0, dec; // dec is declared here.
char input[100], first[100], second[100];
char option;
instructions();
scanf("%s", &option);
while(option != 'q')
{
i = 0;
printf("Base: ");
scanf("%d", &base);
printf("Input: ");
scanf("%s", input);
while(input[i] != '+' && input[i] != '-' && input[i] != '*' && input[i] != '/')
{
i++;
}
printf("%d", i);
if(input[i] == '+')
{
for(j = 0; j < i; j++)
{
first[j] = input[j];
}
first[i] = 0;
dec = baseToDec(base, first); // Error takes place here.
}
}
I know it's a lot of writing, but I listed where the errors take place and the method I pass.
This is wrong:
scanf("%s", &option);
When you use %s, you have to provide a pointer to a string that can hold the entire input. option is a char, not a string. It only has room for a single character, but %s writes the input word followed by a null terminator.
Use %c format to read a single character.
scanf(" %c", &option);
Also,
if (base = 2)
should be
if (base == 2)
But there's no need to treat binary differently from any other base, the conversion process is the same.

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");
}

C program that stops running due to a function be called?

this might be difficult to explain. I am working on a program that takes in a file with numbers in it. the first two numbers are the dimensions of a matrix rows and then columns. the rest of the numbers are the elements of the matrix. what I am having trouble with is that after I created a function to read in a number in a give c style string, the program stops doing anything. It compiles and runs but nothing is ever done, not even printing the first line after main.
proj2.c
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
float readNum(char* buffer, int *pos);
int main(){
char buffer[512];
printf("Enter File Name: ");
//char* fileName = fgets(buffer, sizeof(buffer), stdin);
FILE* file = fopen("matrix.txt", "r");
if(file == NULL){
printf("ERROR COULD NOT OPEN FILE\n");
exit(1);
}
int row = 0;
int col = 0;
int rowcheck = 0;
int colcheck = 0;
int matrixcheck = 0;
while(!feof(file)){
printf("HELLO");
if(fgets(buffer,sizeof(buffer),file) != NULL){
//position of current character
int pos = 0;
//current character
char current;
//loop to determine the dimensions of the matrix
if(colcheck == 0 && rowcheck == 0){
while(colcheck == 0 || rowcheck == 0){
//set current character
current = buffer[pos];
//determine if current character is a number and that the nex character is a space
//for single digit row dimensions
if(current >= '0' && current <= '9' && buffer[pos+1] == ' ' && rowcheck == 0){
row += current - '0';
rowcheck = 1;
}
//if not single digit row dimension add the current character times 10
//and repeat loop to obtain the second digit
else if (buffer[pos+1] >= '0' && buffer[pos+1] <= '9' && rowcheck == 0){
row += (current - '0') * 10;
}
//for columns check if current character is a number and if the next character is space or newline
//and that row has already been checked
else if(current >= '0' && current <= '9' && (buffer[pos+1] == ' ' || buffer[pos+1] == 10) && rowcheck == 1){
col += current - '0';
colcheck = 1;
}
//final check for if columns is double digit so check if next char is a number and that current char is
//not a space
else if(buffer[pos] != ' ' && buffer[pos+1] >= '0' && buffer[pos+1] <= '9' && rowcheck == 1){
col += (current - '0' ) * 10;
}
pos++;
printf("rows: %d cols: %d", row,col);
}
}
//condition to ensure columns and rows have been determined
else if(colcheck == 1 && rowcheck == 1){
//loop to find the elements of the matrix
while(matrixcheck == 0){
current = buffer[pos];
if(buffer[pos + 1] != 10){
if((current >= '0' && current <= '9') || current == '-' || current == '.'){
float num = readNum(buffer, &pos);
printf("number: %f", num);
}
}
}
}
}
}
fclose(file);
}
and readNum.c
#include <stdio.h>
#include <math.h>
float readNum(char* buffer,int *pos){
int negative = 1;
int y = 0;
float number = 0;
if(buffer[*pos] == '-'){
negative = -1;
(*pos)++;
}
while(buffer[*pos + y] >= '0' && buffer[*pos + y] <= '9'){
y++;
}
for(int z = 0; z < y; z++){
number += (buffer[*pos + z] - 48) * pow(10, y - z - 1);
}
*pos += y;
if(buffer[*pos] == '.'){
(*pos)++;
int d = 0;
while(buffer[*pos + d] >= '0' && buffer[*pos + d] <= '9'){
if(buffer[d + *pos] == '.'){
printf("ERROR: multiple decimals in an element");
}
d++;
}
for(int z = 0; z < d; z++){
number += (buffer[z + *pos] - '0') * pow(10, -z - 1);
}
pos += d;
}
return number * negative;
}
commenting out the lines
float num = readNum(buffer, &pos);
printf("number: %f", num);
allows the program to run normally, but uncommenting them it just stops doing anything, in eclipse the console just stays blank running something or other and I terminate it after a bit because nothing is happening, not even the first line is being printed.
this is a sample file that is being read
3 2
56 12 98 25
34.5
45
Thank you in advance
SOLUTION has been found, i'm not sure if everyone understood what exactly is happening in the program. main would not run at all, the first line would not print anything. the solution to this was using fflush(stdout) after the first print statement.
Parsing the file character by character is way to complicated when you are
trying to read floats. Use the function provided by the standard library.
Your code can yield undefined behaviour, because you don't check the boundaries
of buffer, for example:
if(current >= '0' && current <= '9' && buffer[pos+1] == ' ' && rowcheck == 0){
row += current - '0';
rowcheck = 1;
}
You never check if your read the '\0'-terminating byte and keep incrementing
pos, buffer[pos+1] might access beyond the limit. Also I don't understand
how you are really parsing the dimensions. That's why I tell you, don't reinvent
the wheel, use the tools at your disposal.
You say that the dimensions are in the first line, then you can get the
dimension by doing this:
char buffer[512];
if(fgets(buffer, sizeof buffer, file) == NULL)
{
fprintf(stderr, "File is empty\n");
flcose(file);
return 1;
}
size_t cols,rows;
if(fscanf("%zu %zu", &rows, &cols) != 2)
{
fprintf(stderr, "Invalid file format, cannot get columns and rows\n");
fclose(file);
return 1;
}
if(rows == 0 || cols == 0)
{
fprintf(stderr, "Invalid dimension %zux%zu\n", rows, cols);
fclose(file);
return 1;
}
Now, you can parse the file like this:
float matrix[rows][cols] = { 0 };
for(size_t i = 0; i < rows; ++i)
{
if(fgets(buffer, sizeof buffer, file) == NULL)
{
fprintf(stderr, "End of file reached before filling matrix\n");
fclose(file);
return 1;
}
int pos;
char *scan = buffer;
for(size_t j = 0; j < cols; ++j)
{
if(sscanf(scan, "%f%n", matrix[i] + j, &pos) != 1)
{
fprintf(stderr, "Invalid format at line %zu\n", i+2);
break; // continue parsing with the next line
}
scan += pos;
}
}
fclose(file);
printf("matrix[%zu][%zu] = %f\n", rows/2, cols/2, matrix[rows/2][cols/row]);
This code is more robust, because it checks if the functions are working as
intended. If no more lines can be read before the the matrix is filled, then you
can return an error message and end the program. If the lines don't have the
proper format, I ignore that line and the row is filled with 0 while also
printing an error message. If there are more lines than rows, they are ignored
and you would not overflow the buffers. The intentions are also more clear and
it's easier to understand what I'm doing.
Like I said at the beginning, using the function provided by the standard C
library is better than trying to invent the wheel again. Your code is
complicated and hard to read.
Also see why is while(feof) always wrong. It's easier to manage the end
of file when using fgets, because fgets returns NULL when no more data can
be read, either because of an I/O error or because the file reached EOF. That's
why my example above always checks the return value of fgets. Note how I use
%n in the scanf format: %n returns the number of characters consumed thus
far from the input, which is a great info when using sscanf in a loop. I also
check if scanf doesn't return the number of matched elements (note that %n
does not increase the number of matched elements). For more information about
this see the documentation of scanf.
This loop can run forever:
while(buffer[*pos] >= '0' && buffer[*pos] <= '9'){
y++;
}
How can we get out of this loop?:
while(matrixcheck == 0){
current = buffer[pos];
if(buffer[pos + 1] != 10){
if((current >= '0' && current <= '9') || current == '-' || current == '.'){
float num = readNum(buffer, &pos);
printf("number: %f", num);
}
}
}
SOLUTION has been found, i'm not sure if everyone understood what exactly is happening in the program. main would not run at all, the first line would not print anything. the solution to this was using fflush(stdout) after the first print statement.

How to expect different data types in scanf()?

I'm developing a chess game in C just for practicing. At the beginning of the game, the user can type 4 things:
ROW<whitespace>COL (i.e. 2 2)
'h' for help
'q' to quit
How can I use a scanf to expect 2 integers or 1 char?
Seems like it would be most sensible to read a whole line, and then decide what it contains. This will not include using scanf, since it would consume the contents stdin stream.
Try something like this :
char input[128] = {0};
unsigned int row, col;
if(fgets(input, sizeof(input), stdin))
{
if(input[0] == 'h' && input[1] == '\n' && input[2] == '\0')
{
// help
}
else if(input[0] == 'q' && input[1] == '\n' && input[2] == '\0')
{
// quit
}
else if((sscanf(input, "%u %u\n", &row, &col) == 2))
{
// row and column
}
else
{
// error
}
}
It's better to avoid using scanf at all. It usually causes more trouble than what it solves.
One possible solution is to use fgets to get the whole line and then use strcmp to see if the user typed 'h' or 'q'. If not, use sscanf to get row and column.
This one is just using scanf
#include <stdio.h>
int main()
{
char c;
int row, col;
scanf("%c", &c);
if (c == 'h')
return 0;
if (c == 'q')
return 0;
if (isdigit(c)) {
row = c - '0';
scanf("%d", &col);
printf("row %d col %d", row, col);
}
return 0;
}
int row, col;
char cmd;
char *s = NULL;
int slen = 0;
if (getline(&s, &slen, stdin) != -1) {
if (sscanf(s, "%d %d", &row, &col) == 2) {
free(s);
// use row and col
}
else if (sscanf(s, "%c", &cmd) == 1) {
free(s);
// use cmd
}
else {
// error
}
}
P.S.: those who did not read and understand my answer carefully, please respect yourself, DO NOT VOTE-DOWN AT WILL!
Beside "get the whole line and then use sscanf", read char by char until '\n' was entered is also a better way. If the program encountered 'h' or 'q', it could do the relevant action immediately, meanwhile you cloud also provide a realtime analysis for the input stream.
example:
#define ROW_IDX 0
#define COL_IDX 1
int c;
int buffer[2] = {0,0};
int buff_pos;
while( (c = getchar())) {
if (c == '\n') {
//a line was finished
/*
row = buffer[ROW_IDX];
col = buffer[COL_IDX];
*/
buff_pos = 0;
memset(buffer , 0 , sizeof(buffer));//clear the buffer after do sth...
} else if (c == 'h') {
//help
} else if (c == 'q') {
//quit
} else {
//assume the input is valid number, u'd better verify whether input is between '0' and '9'
if (c == ' ') {
//meet whitespace, switch the buffer from 'row' to 'col'
++buff_pos;
} else {
buffer[buff_pos%2] *= 10;
buffer[buff_pos%2] += c - '0';
}
}
}

Detecting combination of characters from input

My task is:
Write a program that reads input up to # and reports the number of times that the sequence ei occurs.
I wrote something that in most of the times works, but there are inputs when it dosent...
Like this input:(suppose to return 1)
sdlksldksdlskd
sdlsklsdks
sldklsdkeisldksdlk
#
number of combination is: 0
This is the code:
int main(void)
{
int index = 0;
int combinationTimes = 0;
int total = 0;
char userInput;
char wordChar[index];
printf("please enter your input:\n");
while ((userInput = getchar()) != '#')
{
if (userInput == '\n')
continue;
wordChar[index] = userInput;
index++;
total++;
}
for (index = 1; index < total; index++)
{
if (wordChar[index] == 'i')
{
if (wordChar[--index] == 'e')
{
combinationTimes++;
++index;
}
}
}
printf("number of combination is: %d", combinationTimes);
return 0;
}
Can you please tell me what am I not getting 1 using this input?
in the book he said to test it with "Receive your eieio award" and it worked...but after i played with it a little i see that not always.
It really doesn't seem necessary to read the file into an array. You just need to keep track of how many times ei is found before you read a # or reach EOF:
#include <stdio.h>
int main(void)
{
int c;
int ei_count = 0;
while ((c = getchar()) != EOF && c != '#')
{
if (c == 'e')
{
int c1 = getchar();
if (c1 == 'i')
ei_count++;
else if (c1 != EOF)
ungetc(c1, stdin);
}
}
printf("ei appeared %d times\n", ei_count);
return(0);
}
Testing (the program is called ei and is built from ei.c):
$ ei < ei.c
ei appeared 0 times
$ sed 1d ei.c | ei
ei appeared 1 times
$ sed 's/#/#/' ei.c | ei
ei appeared 4 times
$
The first one stops at the #include line, the second stops at the # in the comparison, and the third reads the entire file. It also gives the correct output for the sample data.
Analysing the code
Your primary problem is that you do not allocate any space for the array. Change the dimension of the array from index to, say, 4096. That'll be big enough for your testing purposes (but really the program should pay attention to the array and not overflowing it β€” but then I don't think the array is necessary at all; see the code above).
The next primary problem is that despite its name, getchar() returns an int, not a char. It can return any valid character plus a distinct value, EOF. So it must return a value that's bigger than a char. (One of two things happens if you use char. If char is a signed type, some valid character β€” often ΓΏ, y-umlaut, U+00FF, LATIN SMALL LETTER Y WITH DIAERESIS β€” is also treated as EOF even though it is just a character. If char is an unsigned type, then no input matches EOF. Neither is correct behaviour.)
Fixing that is easy, but your code does not detect EOF. Always handle EOF; the data may be malformatted. That's a simple fix in the code.
A tertiary problem is that the printf() statement does not end with a newline; it should.
Your test condition here is odd:
if (wordChar[--index] == 'e')
{
combinationTimes++;
++index;
}
It's odd to use one pre-increment and one post-increment, but that's just a consistency issue.
Worse, though, is what happens when the character i appears in the input and is not preceded by e. Consider the line #include <stdio.h>: you start with index as 1; that is an i, so you decrement index, but wordChar[0] is not an e, so you don't increment it again, but the end of the loop does, so the loop checks index 1 again, and keeps on going around the loop testing that the i is i and # is not e for a long time.
There's no reason to decrement and then increment index; just use:
if (wordChar[index-1] == 'e')
combinationTimes++;
With those fixed, your code behaves. You trouble was largely that you were using an array that was not big enough (being size 0), and you were overwriting quasi-random memory with the data you were reading.
#include <stdio.h>
int main(void)
{
int index = 0;
int combinationTimes = 0;
int total = 0;
int userInput;
char wordChar[4096];
printf("please enter your input:\n");
while ((userInput = getchar()) != '#' && userInput != EOF)
{
if (userInput == '\n')
continue;
wordChar[index] = userInput;
index++;
total++;
}
printf("total: %d\n", total);
for (index = 1; index < total; index++)
{
if (wordChar[index] == 'i')
{
if (wordChar[index-1] == 'e')
combinationTimes++;
}
}
printf("number of combination is: %d\n", combinationTimes);
return 0;
}
Note that you could reasonably write the nested if as:
if (wordChar[index] == 'i' && wordChar[index-1] == 'e')
combinationTimes++;
change your wordChar array value.
int main(void)
{
int index = 0;
int combinationTimes = 0;
int total = 0;
char userInput;
//char wordChar[index]; // index = 0
char wordChar[255]; // should change the value of array.
printf("please enter your input:\n");
while ((userInput = getchar()) != '#')
{
if (userInput == '\n')
continue;
wordChar[index] = userInput;
index++;
total++;
}
for (index = 1; index < total; index++)
{
if (wordChar[index] == 'i')
{
if (wordChar[--index] == 'e')
{
combinationTimes++;
++index;
}
}
}
printf("number of combination is: %d", combinationTimes);
return 0;
}
or maybe you can use pointer and then use malloc and realloc.

Resources