The error is referencing the following line of code:
tenant[i].name = get_string("Enter the residents name: ");
and has an arrow pointing at the period . between tenant[i] and name. I am not sure what I am missing.
typedef struct {
string name;
int apt;
} tenant;
int n;
int numres(void);
string nameres(int numres);
int apt(int numofres);
int main(void) {
int numres(void);
tenant tenants[n];
string nameres(int n);
int apt(int n);
for (int m = 0; m < n; m++) {
printf("Resident %s resides in apt# %i\n",
tenants[m].name, tenants[m].apt);
}
return 0;
}
//this function prompts the user for the number of residents
int numres(void) {
do {
n = get_int("Enter the number of residents: ");
} while (isalpha(n) != 0 || isspace(n) != 0);
return n;
}
// this function prompts the user for the residents names.
string nameres(int numres) {
int i = 0;
do {
tenant[i].name = get_string("Enter the residents name: ");
return tenant[i].name;
i++;
} while (i < numres);
}
// this function prompts the user for the residents apt number
int apt(int numofres) {
for (int i = 0; i < numofres; i++) {
tenant[i].apt = get_int("Enter residents apt number: ");
return tenant[i].apt;
}
}
There are multiple problems in the code:
the string type is not a standard C type, it is defined in <cs50.h> as a typedef for char *, which can be quite confusing. Make sure you include <cs50.h> and <stdio.h>.
in the main function, you define tenant tenants[n];, an array with a length specified by a variable that has a value of 0: this has undefined behavior, and the array cannot be used for anything.
in the main function, you declare functions int numres(void);, string nameres(int n); and int apt(int n);. Such declarations should be made at the file scope, and indeed are done so already. You probably meant to call the functions instead, so you should write:
int main(void) {
numres();
tenant tenants[n];
nameres(n);
apt(n);
for (int m = 0; m < n; m++) {
printf("Resident %s resides in apt# %i\n",
tenants[m].name, tenants[m].apt);
}
return 0;
}
But passing the value of n as a global variable is cumbersome and confusing. numres() should return the value and n should be a local variable.
in numres, it does not make sense to test isalpha(n) != 0 || isspace(n) != 0 because n is a number, not the value of a byte read from the input stream. The function get_int already checks for valid input and returns a converted number, you should just check that the number is positive: n > 0.
nameres should be defined as a void function and use a for loop for the case where n has the value 0.
in nameres and apt should receive tenants as an argument as this array is defined locally in main. The code should use tenants instead of tenant, which is a type name. This is the reason for your compilation issue. Using a _t suffix for the types is recommended to avoid such problems.
in nameres and apt should should prompt for the name and apartment numbers of all residents, remove the return statements.
using while or for loops instead of do / while loops allows for more concise code with explicit tests closer to the generating fact.
Here is a modified version:
#include <cs50.h>
#include <stdio.h>
typedef struct tenant_t {
string name;
int apt;
} tenant_t;
int numres(void);
void nameres(tenant_t tenants[], int numres);
void apt(tenant_t tenants[], int numres);
int main() {
int n = numres();
tenant_t tenants[n];
nameres(tenants, n);
apt(tenants, n);
for (int i = 0; i < n; i++) {
printf("Resident %s resides in apt# %i\n",
tenants[i].name, tenants[i].apt);
}
return 0;
}
// this function prompts the user for the number of residents
// it returns the number which must be strictly positive
int numres(void) {
for (;;) {
int n = get_int("Enter the number of residents: ");
if (n > 0)
return n;
}
}
// this function prompts the user for the residents names.
void nameres(tenant_t tenants[], int numres) {
for (int i = 0; i < numres; i++) {
tenants[i].name = get_string("Enter the residents name: ");
}
}
// this function prompts the user for the residents apt number
void apt(tenant_t tenants[], int numres) {
for (int i = 0; i < numres; i++) {
tenants[i].apt = get_int("Enter residents apt number: ");
}
}
Related
Context: I need to write a program that will accept inputs which will be stored into the array. Before storing in to the array, the inputted number must be checked if it already exists in the array or not. If it does not exist, it is stored into the array. If it exists, another input will be asked.
Now, my code will get inputs from the user, but the code will only work for the first input. It won't work for the second until the last input. Any pointers?
This is my code:
#include<stdio.h>
#define size 5
main()
{
int i;
arr[size];
input;
printf("This program will accept ");
printf("unique inputted numbers that will be stored");
printf(" in an array\n");
for(i = 0;i < size;i++)
{
printf("Enter input: ");
scanf("%d",&input);
if (unique(arr,input,i))
arr[i] = input;
else
i--;
//decrement i because ask for input again
}
for(i = 0;i < size;i++)
printf("%d ",arr[i]);
}
int unique(int arr[],int input,int i)
{
int n, z;
n = 0;
z = 1;
while(i > n)
{
if(arr[n] == input)
{
scanf("%d",&n);
z = 0;
break;
}
else
n=1;
break;
}
return z;
}
Your code is wrong at multiple levels:
The logic in the unique function is wrong.
Doing the scanf in the unique function is extremely bad design. The only thing unique should do is return 0 if input is already in the array.
You have used implicit variable declarations here: arr[size]; input;, it should be int arr[size]; int input;.
You should use descriptive variable names which makes your code easier to understand.
This is a working example (explanations in comments).
#include <stdio.h>
#define SIZE 5 // use capitals for macros (this is a convention)
int unique(int arr[], int value, int arrsize)
{
for (int i = 0; i < arrsize; i++)
{
if (arr[i] == value)
{
return 0; // value found in array
}
}
return 1; // value not found in array
}
void Test(int arr[], int arrsize, int value, int expected)
{
if (unique(arr, arrsize, value) != expected)
printf("Test failed for value %d\n", value);
}
void runtests()
{
int arr[] = { 1,2,3 };
Test(arr, 4, sizeof(arr) / sizeof(*arr), 1);
Test(arr, 1, sizeof(arr) / sizeof(*arr), 0);
Test(arr, 3, sizeof(arr) / sizeof(*arr), 0);
}
#define size 5
int main()
{
int i;
int arr[size]; // declare int variable
int input; // declare int variable
printf("This program will accept unique inputted numbers that will be stored in an array\n");
for (i = 0; i < size; i++)
{
printf("Enter input %d: ", i + 1);
scanf("%d", &input);
if (unique(arr, input, i)) // value already in the array?
arr[i] = input; // no => put it there
else
{ // yes => ask again
printf(" >> %d is already in the array\n");
i--;
}
}
for (i = 0; i < size; i++)
printf("%d ", arr[i]);
}
There are two more functions Test and runtests in this code. They are not called by this code, but they can be very useful for debugging. As an exercise try to understand why they can be useful during the debug phase of your code.
You're close, but overcomplicating it slightly.
Let's take a step back and think about this at a high level. You want to store unique inputs in the array, up to the size of the array. In pseudocode:
while array not full
prompt for and read next input
if input not already in array
store input
else
write a message
end if
end while
What's really key is that you only need one input statement - your unique function should only check for the presence of the input value in the array and return true or false. It shouldn't do any input of its own.
So your main loop is more like
while ( i < size )
{
fputs( "Gimme a number: ", stdout );
/**
* Break out of the loop if there's an error
* on input.
*/
if ( scanf( "%d", &input ) != 1 )
break;
if ( unique( arr, i, input ) )
arr[i++] = input;
else
printf( "%d already exists in the array, try again.\n", input );
}
All your unique function needs to do is cycle through the elements of the array. By calling unique with i instead of size it will only check array elements that have been written to so far and not bother with unassigned elements. This way you don't have to make sure that all of the array elements have been initialized to some known, out-of-band value that's guaranteed to compare unequal to any valid input.
You'll need to compile against C99 or later and include stdbool.h to use the bool type and the true and false constants.
#include <stdbool.h>
...
bool unique( int *arr, size_t size, int input )
{
bool result = true;
for( size_t i = 0; i < size && result; i++ )
if ( arr[i] == input )
result = false;
return result;
}
If you want to get really terse, you could directly assign the result of the Boolean expression to result:
for ( size_t i = 0; i < size && result; i++ )
result = (arr[i] == input);
but people will hit you. It's perfectly valid code, but a little eye-stabby, and most programmers aren't used to seeing Boolean expressions outside of an if, for, while, or switch statement control expression.
Finally, some suggestions:
Fix your formatting. The compiler doesn't care, but it makes it easier for other people to understand what you're trying to do and to spot mistakes.
The presence of main() in your code suggests you're using C89 or K&R C. C99 did away with implicit int declarations. You really should define main as either int main( void ) or int main( int argc, char **argv ). Furthermore, you should move to a compiler that supports later versions of C (C11 or C18).
I'm going to make a palindrome which should ignore spaces and special characters and should convert all uppercase letters in the string to lowercase. I have done everything, but when I run my program, neither of these two functions work. Convert uppercase to lowercase and ignore all non-uppercase letters. Could any of you help me to solve what is the problem?
#include<stdio.h>
#define SIZE 1000
#include <ctype.h>
#include<string.h>
// function that checks if it is a palindrome
int isPalindrome(char inputString[]) {
int l = 0;
int r = strlen(inputString) - 1;
while (r > l)
{
// will check all letters are equal to each other
if (inputString[l++] != inputString[r--]) {
return 0;
}// return 0 if not palindrome
}
// palindrome
return 1;
}
// function that ignores all non - letters
int no_special_characters(char inputString[])
{
char temp[SIZE];
int temp_index = 0;
int abc = 0;
int r = strlen(inputString);
for (int i = 0; i < r; i++)
{
char abc = inputString[i];
if (isalpha(abc) != 0)
{
temp[temp_index++] = abc;
}
}
temp[temp_index] = '\0';
return isPalindrome(temp);
}
// function that converts uppercase letters to lowercase
void to_lower(char inputstring[]) {
int length = strlen(inputstring);
for (int i = 0; i < length; i++)
{
if (isupper(inputstring[i]))
inputstring[i] = tolower(inputstring[i]);
else if (islower(inputstring[i]))
inputstring[i] = toupper(inputstring[i]);
}
return 0;
}
int main(void) {
int try_again = 1;
int end_run = 0;
while (try_again == 1) {
int try_again;
char inputString[SIZE] = "";
printf("Enter a string to check if it is a palindrome!\n");
//Scans the input string.
scanf_s("%s", &inputString, SIZE);
//Sends the string to the isPalindrome function. //If the return value is 1(true), the if statement is executed, otherwise the else statement.
if (isPalindrome(inputString)) {
printf("That is a palindrome!\n");
}
else {
printf("This is not a palindrome!\n");
}
printf("Do you want to try again: 1 for yes 0 for No?");
scanf_s("%d", &try_again);
//Changes the value of running depending on whether you want to continue or not.
if (try_again != 1) {
end_run = 0;
}
}
return 0;
}
1 - Don't use scanf
You shouldn't use scanf to read input from the console, especially in a loop. I'm not an expert in scanf_s in particular, but that whole family of functions can cause weird bugs if you don't know how they work. I recommend you read this article, it explains it better that I can.
2 - Your loop doesn't work
You are defining try_again in function scope and then redefining it in block scope: they are two different variables.
Your code is essentially this:
int main(void) {
int try_again = 1;
while (try_again == 1) {
int try_again;
scanf_s("%d", &try_again);
}
}
Which will run forever, since the while loop is checking the first variable, while you are assigning to the second one. It should look more like this:
int main(void) {
int try_again = 1;
while (try_again == 1) {
// int try_again;
// ^^ Don't refefine - use the one already defined
try_again = some_function_to_read_input();
}
}
3 - to_lower doesn't actually convert to lowercase
It converts uppercase to lowercase and lowercase to uppercase. This means "Aa" becomes "aA", which is not a palindrome even though it should be by your definition.
The function doesn't need to return anything, since it changes the string in place. You can simply call it like this:
int isPalindrome(char inputString[]) {
to_lower(inputString);
// Rest of code
}
4 - You aren't calling no_special_characters
You simply aren't calling it. Either you do it in your main, something like:
// main
if (no_special_characters(inputString)) {
// Rest of code
}
Or you change it to return the modified string and call it from inside isPalindrome:
void no_special_characters(char inputString[]) {
// Remove all special characters, in place
}
int isPalindrome(char inputString[]) {
no_special_characters(inputString);
to_lower(inputString);
// Rest of code
}
I have created a password checker in c programming but it is not working can anyone please check it and say what is wrong in this.
#include<stdio.h>
#include<stdbool.h>
int main() {
int otp[4]; //array for storing the true password entered by user at first
int pto[4]; //array for storing password for login
int count = 4,i;
bool pass = true;
printf("enter a new password: ");
for (int i = 0; i < count; i++) {
scanf("%d", & otp[i]); //for storing the true password
}
printf("\n\n --- Login page --- ");
printf("\nenter your password : ");
for (i = 0; i < count; i++) {
scanf(" %d", & pto[i]); //asking for password for login
}
for (i = 0; i < count; i++) { //check for password
if (otp[i] == pto[i]) {
pass = true;
} else {
pass = false;
}
}
while (pass == false) { //if password is wrong
printf("\n---- password din't match ----\nenter your password again : ");
for (i = 0; i < count; i++) {
scanf(" %d", & pto[i]);
}
for (i = 0; i < count; i++) {
if (otp[i] == pto[i]) {
pass = true;
} else {
pass = false;
}
}
}
printf("\n Your password is correct!");
return 0;
}
And should I use int or char to store passwords,if i use int also that part works if char also it works but sometimes it wont work,
This loop ultimately only cares if the last value in each array match or not.
for (i = 0; i < count; i++) {
if (otp[i] == pto[i]) {
pass = true;
} else {
pass = false;
}
}
For example, comparing { 1, 2, 3, 4 } and { 4, 4, 4, 4 } would result in pass being true after the loop, despite the obvious differences.
Instead, set the flag to false, and break from your loop as soon as a mismatch occurs.
bool matching = true;
for (size_t i = 0; i < length; i++) {
if (array_one[i] != array_two[i]) {
matching = false;
break;
}
}
If a mismatch never occurs, the flag will remain true afterwards.
Usually passwords are text that is hashed (with a salt) before being stored. Password verification is done by comparing hashes. For example, take a look at the man 3 crypt library function.
The use of a fixed-length series of plain integers for a 'password' is atypical, but for a toy program it is fine.
Here is an example program to study.
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#define KEY_LENGTH 4
void get_key(int *key, size_t length) {
for (size_t i = 0; i < length; i++) {
if (1 != scanf("%d", &key[i])) {
fprintf(stderr, "Could not read integer input.\n");
exit(EXIT_FAILURE);
}
}
}
bool match_key(int *one, int *two, size_t length) {
for (size_t i = 0; i < length; i++)
if (one[i] != two[i])
return false;
return true;
}
int main(void) {
int key[KEY_LENGTH];
int user_key[KEY_LENGTH];
printf("Set the key (%d integers): ", KEY_LENGTH);
get_key(key, KEY_LENGTH);
puts("--- LOGIN ---");
while (1) {
printf("Enter the key (%d integers): ", KEY_LENGTH);
get_key(user_key, KEY_LENGTH);
if (match_key(key, user_key, KEY_LENGTH))
break;
puts("Key mismatch. Retrying...");
}
puts("Welcome to the system.");
}
Since you didn’t specify your problem (besides “it’s not working”), I’ll do my best to list all the possible issues.
Reading integers
scanf("%d", & otp[i]);
Will read a single decimal integer into a position in otp. If the password is 1024, the first time through the loop (iteration) will read 1024 into otp[0]. In the second iteration, scanf() will wait until another number is available on standard input. Once it’s available, it will read it into otp[1], and so on. This scanf() loop really reads in 4 different integers, separated by newlines. It would be much easier to do only one scanf() for one integer, like this:
int main() {
int otp;
int pto;
bool pass = true;
printf("enter a new password: ");
scanf("%d", &otp);
You could also scan a 4-character string by using char arrays:
int main() {
char otp[5]; //4 digits and 1 NUL-terminator
char pto[5];
bool pass = true;
printf("enter a new password: ");
scanf("%4s", otp);
Password-checking logic error
As #Oka explained, your checker has a logic error. If using an integer, you could simply check
if (opt == pto) {
//correct
} else {
//incorrect
}
If using a char array (string), you could use
if (!strcmp(otp, pto)) {
//correct
} else {
//incorrect
}
You would have to #include <string.h> for strcmp().
Standard output buffer
The “enter a new password: ” prompt is not printed until the stdout buffer is flushed. This usually only happens when a newline is printed. You have to
fflush(stdout);
right after printing the prompt if you want it to appear.
Let's say I have an array of phone numbers: char numbers[4][9] = {"555555534", "112221222", "512221222", "355555534"}; I need to find there phone numbers, that matches a specific pattern.
For example, I can find a number:
5******** that starts with a 5, and the rest of the digits can be ignored (does not matter what they're really)
**2***** the third digit is 2, and the rest of the digits can be ignored (does not matter what they're really)
etc.
The pattern I should look for is given by the user. I wrote a simple test, but somehow I have problems with implementing the number_matches function.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int i,j;
char *findmeplz = "5********";
char numbers[4][9] = {"555555534", "112221222", "512221222", "355555534"};
for (i=0; i<4; i++)
{
if(number_matches(numbers[i], findmeplz))
{
printf("number found on position %d\n", i);
break;
}
}
return 0;
}
The function can be like the following:
int number_matches(char* number, char* pattern)
{
int i = 0, flag = 1;
for(i = 0; i < strlen(pattern); i++)
{
if(pattern[i] != '*')
{
if(pattern[i] != number[i])
{
flag = 0;
break;
}
}
}
return flag;
}
I'm trying to write a program that gets a string, and a number, and calculates the length of it and shifting all the elents right.
I have 2 errors:
1.assignment makes pointer from integer without a cast.
2.assignment makes integer from pointer without a cast.
#include <stdio.h>
#include <string.h>
#define N 10
int myStrlen(char*);
void shiftRight(char*, int);
int main() {
char str[N] = {0};
int num = 0;
int len;
/* input of the string */
scanf("%s",str);
scanf("%d",&num);
len=myStrlen(str);
if(num>=0) {
shiftRight(str, num);
printf("%s\n",str);
}
else
{
printf("%s\n", str);
}
return 0;
}
int myStrlen(char*str)
{
int my_len=0;
while (str[my_len] != '\0')
{
my_len++;
}
return my_len;
}
void shiftRight(char* str, int num)
{
int i;
char* j;
int count;
j=(str[N-1]);
for(count=0;count<num;count++)
{
for(i=N-1;i>0;--i)
{
str[i]=str[i-1];
}
str[0]=j;
}
}
Your answers are welcome,anf if you anything wrong with this code,please mention it.
As your compiler will have told you, pointer from integer without a cast is at
j=(str[N-1]);
And integer from pointer is at
str[0]=j;
You should have declared j as char j;
But now when i run it, and typing lets say ball as a string and 1 to
be a number, i get nothing from the program instead of getting "lbal"
You have all the correct elements but that's not enough. Writing a program is telling a story, you need to set the scene, describe what happens along the way and conclude your narrative. A story with elements out of order is nonsense, as is a program.
Specific issues with your code: you're saving of the last character (to restore it to the beginning of the string) is in the wrong place; you're using the allocation of the string when you should be using it's length (and conveniently, you have a function for that!); this is really more of a rotation than a shift; use the most descriptive variable names you can, not the shortest you can get away with; pick one indentation style and stick with it -- it can change between programs you write but shouldn't change within an individual program.
Below is a rework of your code addressing some of the issues above:
#include <stdio.h>
#define STRING_SIZE 10
int myStrlen(char *string)
{
int length = 0;
while (string[length] != '\0')
{
length++;
}
return length;
}
void rotateRight(char *string, int number)
{
int length = myStrlen(string);
for (int count = 0; count < number; count++)
{
char j = string[length - 1];
for (int i = length - 1; i > 0; i--)
{
string[i] = string[i - 1];
}
string[0] = j;
}
}
int main()
{
char string[STRING_SIZE] = {0};
int number = 0;
/* input of the string */
scanf("%s", string);
scanf("%d", &number);
if (number > 0)
{
rotateRight(string, number);
printf("%s\n", string);
}
else
{
printf("%s\n", string);
}
return 0;
}
OUTPUT
% ./a.out
elephant
3
anteleph
%