I am having trouble trying to get the "isZero" function to detect if the word is an anagram or not. Asking if "isZero" is equal to 1 in main() it will only give me "anagram". And if i set it to 0 it will only give me "not anagram". To me it is not computing anything, it is just printing out whatever statement is true at the moment. Not sure how to solve this and could use some guidance.
#include <stdio.h>
#include <ctype.h>
#define MAX 26
void intialize(char a[], char b[], int c[]);
void setLetters(char newCount[], int newNumber[]);
void checkLetters(char b[], int newNumber[]);
int isZero(int c[]);
void getstring(char a[]);
void getString(char b[]);
int main(void)
{
char a[MAX], b[MAX];
int c[MAX];
intialize( a, b, c);
getstring(a);
getString(b);
setLetters(a, c);
checkLetters(b, c);
if (isZero(c) == 1) {
printf("anagram");
} else
printf("not anagram");
return 0;
}
void intialize(char a[], char b[], int c[])
{
int i;
for(i = 0; i < MAX; ++i) {
a[i] = '\0';
b[i] = '\0';
c[i] = 0;
}
}
void setLetters(char newCount[], int newNumber[])
{
int i, index = 0;
for(i = 0; i < MAX; ++i) {
if(isalpha(newCount[i])) {
newCount[i] = tolower(newCount[i]);
index = (int)(newCount[i] - 'a');
newNumber[index] +=1;
}
}
}
void checkLetters(char b[], int newNumber[])
{
int i, index;
for(i = 0; i < MAX; ++i) {
if(isalpha(newNumber[i])) {
newNumber[i] = tolower(newNumber[i]);
index = (int)(newNumber[i] - 'a');
newNumber[index] -= 1;
}
}
}
int isZero(int c[])
{
int i, j = 0;
for(i = 0; i < MAX; ++i) {
if(c[i] == 0)
j = 1;
else
return 0;
}
return j;
}
void getstring(char a[])
{
char line[MAX];
printf("Enter a string: ");
gets(line);
}
void getString(char b[])
{
char line[MAX];
printf("Enter a string: ");
gets(line);
}
With C it is mandatory that you slow down and understand what each part of each line does. There is no part of C where close enough is correct. That being said, you had an overall idea about how to approach the problem. However, it was very clear that you are just starting out in C (given the other answers and comments).
Before you start writing functions, determine what you need a function to do. Then try and determine how best to handle that task. If you need a function to get string input, then write one to do that. If you find yourself having to write one function to fill each string stop, your have just defeated the purpose of the function. Writing a function to do the same thing for a[] and another identical function for b[] makes no sense. You don't need a function to loop through all arrays setting your newly declared arrays to zero/NULL, that's what array initialization syntax is for.
Before you expect to have functions work, take the time to learn how to pass values to (and if a return is needed -- get values from) a function. When you pass an array to a function, pointer decay occurs. That means array a[] decays to *a when passed to a function. You can take advantage of this by declaring your functions to accept *a as the argument. While this isn't earth-shattering for a simple 1-D array, the decay becomes more involved with 2-D arrays and above.
In addition to figuring out which code makes sense as a function, you need to be just as exact with your logic in C as you are with its syntax. If there is any part of a line your are unsure about, look it up, look at the man page for the function you are using, or consult a language reference for your compiler (Gnu/MS), etc. to make sure you know exactly what your code does. It will save you time in the long run. The number one thing that trips new C programmers up, is trying to skim the manual or skim the book and then start writing code. The key to learning C is to just slow down.
Never, Never, Never use gets(). If you are taking a class and the teacher hands you an assignment using it, go to administration and ask for a refund. gets() is no longer part of the standard C library due to how easily it is compromised and exploited. Use fgets, getline, or scanf (read the entire section on proper use of the scanf format string if you chose to use it). It is a fine function, but it has many, many pitfalls just waiting for someone that partially understands its use.
That being said, you had the overall logic for one approach to anagrams. Below I've provided an example of the points above in sorting out your code. Take the time to read through it and understand why I made the changes I did. Additionally, I added a quick length check for the words input. If they are not the same length, no need to go further. Let me know if you have questions. There are a lot of good folks here that are happy to help.
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#define MAX 26
void setLetters(char *newCount, int *newNumber);
void checkLetters(char *newCount, int *newNumber);
int isZero (int *c);
void getstring (char *a);
int main (void)
{
char a[MAX] = {0}; /* initialize all to zero/NULL */
char b[MAX] = {0};
int c[MAX] = {0};
getstring(a);
getstring(b);
printf ("\n You entered:\n\n a: %s\n b: %s\n\n", a, b);
/* test lengths - if differ, not anagram */
if (strlen(a) != strlen(b)) {
printf (" Lenghts differ, cannot be an anagram.\n\n");
return 1;
}
setLetters (a, c); /* set key array (c) */
checkLetters (b, c); /* check key array (c) */
if (isZero(c))
printf(" The words form an anagram.\n\n");
else
printf(" The words are not and anagram.\n\n");
return 0;
}
void setLetters (char *newCount, int *newNumber)
{
int i = 0;
int index = 0;
for (i = 0; i < MAX; ++i) {
if (isalpha (newCount[i])) {
newCount[i] = tolower (newCount[i]);
index = (int)(newCount[i] - 'a');
newNumber[index] +=1;
}
}
}
void checkLetters(char *newCount, int *newNumber)
{
int i = 0;
int index = 0;
for (i = 0; i < MAX; ++i) {
if (isalpha (newCount[i])) {
newCount[i] = tolower (newCount[i]);
index = (int)(newCount[i] - 'a');
newNumber[index] -= 1;
}
}
}
int isZero (int *c)
{
int i = 0;
for (i = 0; i < MAX; ++i)
if (c[i] == 1)
return 0;
return 1;
}
void getstring (char *a)
{
printf ("\n Enter a string: ");
scanf ("%[^\n]%*c", a);
}
output:
$ ./bin/anaproj
Enter a string: yekcim
Enter a string: mickey
You entered:
a: yekcim
b: mickey
The words form an anagram.
$ ./bin/anaproj
Enter a string: yekcim
Enter a string: mickez
You entered:
a: yekcim
b: mickez
The words are not and anagram.
void getstring(char a[]);
This API is not doing what you intend to do.
This has a local variable line and your are reading a string to it and the char array in main() i.e. a is never been filled up with anything.
You continue to use the char array a thinking the values are filled in it by calling getstring() which is not happening. You need to fix this first and later work on the algorithm for anagram.
There is something called pass by reference which might help you.
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 got a task from my college which is to find the length of a string using pointers in a function.Here is my code:
#include <stdio.h>
#include <stdlib.h>
#define max 100
int lengthchar(char *array1[])
{
int a, x = 0;
for (a = 0; *(array1++) != '\0'; a++)
{
x++;
}
return x;
}
int main()
{
char arr1[max];
int length;
printf("Enter string\n");
gets(arr1);
length = lengthchar(arr1);
printf("Length=%d", length);
return 0;
}
But when I give input something bellow:
Enter string: av
Length=9
It shows the wrong length, what's my mistake?
This is because of the way to pass a string pointer as an argument to the function.
Just change char *array1[] to char *array1 or array1[].
Have a look at the implementation below:
int lengthchar(char array1[])
{
int a,x=0;
for(a=0;*(array1++)!='\0';a++)
{
x++;
}
return x;
}
PS: variable a can be removed by using a while loop.
In your function signature, you are telling the compiler that lenghtchar() expects a pointer to character strings, or **char in other words.
What you really want to do is to change your function from int lengthchar(char *array1[]) to int lengthchar(char array1[]) or int lengthchar(char *array1). This is a bit tricky since in C, you can address an array by using the address of its first element (aka, by using pointer to its first item).
Expert C Programming has a dedicated chapter on this topic.
Now, coming to your lengthchar() function, I would do some refactoring to eliminate the variable a and use a while loop instead. I have also included another alternative implementation that relies on pointer arithmetic (more fun to me :) )
Note also that I used fgets() instead of gets() which is considered deprecated since it does not do any bounds checking.
#include <stdio.h>
#include <stdlib.h>
#define max 100
/*
* returns the lenght of the string excluding the terminating
* NULL character
*/
int lengthchar(char *array1) {
int x = 0;
while (*array1++)
x++;
return x-1;
}
int lengthchar1(char *array1){
char *p;
for (p = array1; *p; p++)
;
return p - array1 - 1; /* -1 for \0 */
}
int main() {
char arr1[max];
int length;
printf("Enter string\n");
fgets(arr1, max, stdin);
length = lengthchar(arr1);
printf("Length=%d", length);
return 0;
}
On declaring or defining a function that shall take an array of type T as an argument, use the notation: T *array or T array[]; T may stand for any valid C data type such as char, int, float, double, etc...
As for your loop, the variable a seems to be redundant because it has no effect on any part of the program. The return value of the function lengthchar() is one more than the number of characters inputted.
Also you should avoid the function gets() because it is deemed dangerous and has been removed from the C standard; use fgets() instead.
Your code should look something like this:
#include <stdio.h>
#include <string.h>
#define max 100
int lengthchar(char *str)
{
int len = 0;
while (*str++)
{
len++;
}
return len;
}
int main()
{
char str1[max];
printf("Enter string:");
fgets(str1, max, stdin);
str1[strcspn(str1, "\n")] = 0; // remove new-line character
int length = lengthchar(str1);
printf("Length = %d\n", length);
return 0;
}
#include <stdio.h>
#include <string.h>
void replace(char a[],char b[]);
int main(void)
{
char string1[100]; char string2[100];
printf("Please enter a string:");
fgets(string1, sizeof(string1), stdin);
replace(string1, string2);
}
void replace(char a[],char b[])
{
int i;
strcpy(b,a);
for(i=0;i<strlen(a);i++)
{
if(a[i]=='a')
{
b[i+1]=a[i];
}
}
printf("%s\n",b);
}
The function of this program is to copy string1 into string2 but if there's any 'a' character in string1, it needed to be double in string2.
For example, if string1 is "aeroplane", the string2 needs to be "aaeroplaane".
However, the code above seem to change the next character after 'a' in string1 instead of simply adding it. For example, if I type "aloha", it will simply give me "aaoha" instead of "aalohaa". I've tried searching online but to no avail. I've been sticking on this problem for hours.
In order to work you must implement your replace function correctly
It should be like:
void replace(char a[],char b[])
{
int idxA = 0, idxB = 0;
for(idxA;idxA<strlen(a);idxA++, idxB++)
{
b[idxB] = a[idxA];
if(a[idxA]=='a')
{
idxB++;
b[idxB]=a[idxA];
}
}
b[idxB] = '\0';
printf("%s\n",b);
}
But you must ensure b has enough space to hold the complete string. For example, you can reserve twice the size of a, the worst case when array a has all a characters
Ok, if we are playing code golf, I would suggest:
void replace (char *a, char *b) {
while ((*b++ = *a))
if (*a++ == 'a')
*b++ = 'a';
}
;)
Mind to provide enough memory in b; if you want to play it safe, it has to be at least strlen(a)*2+1 (the case a consists only of character "a").
For the sake of brevity and elegance, here's a one liner:
void replace (char *a, char *b) { while((*b++=*a)&&(*a++!='a'||(*b++='a'))); }
;)
with
b[i+1]=a[i]
you're changing the next character to be 'a' and overwriting the next character.
What should be done is moving all the characters after b[i+1] one step forward and then changing 'a' in b[i+a]
void replace(char a[],char b[])
{
int i = 0, j = 0;
for(i=0; i<strlen(a); i++, j++)
{
b[j] = a[i];
if(a[i] == 'a')
b[++j] = a[i];
}
}
see if this works.
I wont solve it for you.
But here is what you need to look into.
if(a[i]=='a')
{
b[i+1]=a[i];
}
What it is doing is, if ith index of a array is 'a' then write ith index of a array in i+1th location of array b.
This way you are over-writing the contents of b.
You need to make a place for an additional character there only after shifting the string from that index to right.
It can be done in multiple ways.
Additionally, you might want to allocate more size (ideally twice: To cover the case when you pass a string1 with 100 'a's, the resulting string2 should hold 200 'a's) to your second array than the first one, because of obvious reasons.
You want this:
#include <stdio.h>
#include <string.h>
void replace(char a[], char b[]);
int main(void)
{
char string1[100]; char string2[100];
printf("Please enter a string:");
fgets(string1, sizeof(string1), stdin);
replace(string1, string2);
printf("%s\n", string2); // printf result from replace here
}
void replace(char a[], char b[])
{
int i, j; // using two indexes, one for a and one for b
// no strcpy needed here, copying is done in the for loop below
for (i = 0, j = 0; i < strlen(a); i++, j++)
{
b[j] = a[i]; // copy one char
if (a[i] == 'a') // if it's 'a'
{
b[++j] = a[i]; // copy it again
}
}
b[j] = 0; // terminate the destination string
// we don't printf b here but in main
}
For brevity no buffer overflow checking is done here.
There is still room for improvement though.
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
%
I am trying to make a program that converts a hex string into decimal. However I am having an issue assigning a returned integer value from the findLength function. Going by the printf statements I can tell that findLength(theString) will yield the correct value however length is showing a value of 0 despite the fact that I have length = findlength(theString).
This isn't a homework problem, I'm just absolutely stumped as to why this simple assignment isn't working. I've already declared length so I know that's not the issue. I'm also getting no compiler messages. Any help would be greatly appreciated.
Edit: I know convert doesn't do anything useful and the for loop needs to be fixed however that shouldn't be effecting the findLength return right?
Second Edit:
I've always submitted a string of '324' to be tested.
#include <stdio.h>
int convert(char s[], int theLength);
int findLength(char s[]);
int main(){
char theString[100];
int result;
int i;
int length;
printf("%s","Hello, please enter a string below. Press enter when finished.");
scanf("%s",theString); //Apparently scanf is bad but we'll learn better input methods later.
//For my tests I submitted a string of '324'.
length = (findLength(theString)); //length = findLength('324')
printf("%d",findLength(theString)); //yields 3
printf("%d",length); //yields value of 0 always.
result = convert(theString, length);
printf("%d\n result is",result);
return 0;
} //End of main
int convert(char s[], int theLength){ //This function will eventually converts a string of hex into ints. As of now it does nothing useful.
int i;
int sum;
for(i = theLength; i=0; i--){
sum = sum + s[i];
printf("%d\n",sum);
}
return sum;
} //End of convert
int findLength(char s[]){
int i;
for(i = 0; s[i]!='\0'; ++i){
}
return(i);
} //End of findLength
The variable length is storing the correct value. I think what has you confused is how you've laid out your printf statements. If you were to try something like the below it would be much easier to see that your code works.
#include <stdio.h>
int findLength(char s[]);
int main(){
char theString[100];
int result;
int i;
int length;
printf("Hello, please enter a string below. Press enter when finished.\n");
scanf("%s",theString);
length = (findLength(theString));
printf("findLength(theString) = %d\n",findLength(theString));
printf("length = %d\n",length);
return 0;
}
int findLength(char s[]){
int i;
for(i = 0; s[i]!='\0'; ++i){
}
return(i);
}
Just to clarify in your post you have
printf("%d",findLength(theString));
printf("%d",length);
printf("%d\n result is",result);
Note the \n before the %d in the last printf statement. This is 0 because your convert function needs to be fixed and this is the value of result NOT length.