#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.
Related
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 5 years ago.
Improve this question
This is my code and prints error. I think it should work fine but there is an error with the squeeze function and I cannot find what.
#include <stdio.h>
void squeeze(char *s, int c);
int main(void){
char s[]="kyriacos";
squeeze(s,'c');
printf("the new kyriacos is %s",s);
}
void squeeze(char *s, int c){
int i,j;
for(i=j=0; s[i]!='0';i++){
if(s[i]!='c'){
s[j]=s[i];
j++;
}
}
s[j]='\0';
}
Your function implementation has a typo. In the condition of this statement
for(i=j=0; s[i]!='0';i++){
there must be used character '\0' instead of '0'.
for(i=j=0; s[i]!='\0';i++){
And one more typo is in this statement
if(s[i]!='c'){
Instead of the character 'c' you need to use the parameter c.
if(s[i] != c){
Take into account that string functions usually follow the convention that they return pointer to the target string.
So it is better to declare the function like
char * squeeze(char *s, int c);
Also instead of using the type int as the type of indices for strings it is better to use the type size_t because it is the type that the standard function strlen and results of the applying operator sizeof have.
Here in the demonstrative program is shown how the function can be implemented
#include <stdio.h>
char * squeeze(char *s, int c)
{
size_t i = 0, j = 0;
do
{
if (s[i] != c)
{
if (i != j) s[j] = s[i];
j++;
}
} while (s[i++]);
return s;
}
int main( void )
{
char s[] = "kyriacos";
printf("the new kyriacos is \"%s\"\n", squeeze(s, 'c'));
}
The program output is
the new kyriacos is "kyriaos"
The for does not know when to end. When it reaches the last letter of your word it just goes on. The solution would be : i < strlen(s) . To use strlen you must include string.h in the headers! Good luck!
for(i=j=0;i < strlen(s);i++)
or you could go with
for(i=j=0; s[i]!='\0';i++) // '\0' is the end string character
You have:
void squeeze(char *s, int c){
int i,j;
for(i=j=0; s[i]!='0';i++){
if(s[i]!='c'){
s[j]=s[i];
j++;
}
}
s[j]='\0';
}
The 'c' is a mistake; you want to use the variable c. You also need to test for '\0' (rather than '0') to terminate the loop.
void squeeze(char *s, int c)
{
int i, j;
for (i = j = 0; s[i] != '\0'; i++)
{
if (s[i] != c)
s[j++] = s[i];
}
s[j] = '\0';
}
Blanks are cheap; use them. The increment operators can be used (carefully) in expressions.
A concern in addtion to other fine answers:
#jacoblaw points out issues relating to the type of c. This is important when char can have a negative value, yet the value passed in is via int c.
void squeeze1(char *s, int c) {
size_t j = 0;
for(size_t i=0; s[i]; i++) {
// This could be comparing a negative `char` against a int value like CHAR_MAX + 10
if(s[i] != c) {
s[j++]=s[i];
}
}
s[j]='\0';
}
void foo() {
char s[80];
fgets(s, sizeof s, stdin);
int ch = fgetchar(); // ch has a value in the `unsigned char` range.
if (ch != EOF) squeeze1(s, ch);
}
C11 7.24 String handling
... For all functions in this subclause, each character shall be interpreted as if it had the type unsigned char ...
The standard C library tends to treat char as unsigned char for comparison purposes so suggest alternate approaches
void squeeze2(char *s, char c) {
or
void squeeze3(char *s, int c) {
...
if((unsigned char) s[i] != (unsigned char) c) {
When u pass s in squeeze(s,'c') it onlypasses the address of the first char of the string. To access the value at address u need to dereference the pointer(use *).
To access the next value make the pointer s point to next address using (s++) i.e it points to next address where a new char is stored which is after 1 byte.
The problem is with the loop, u need to access the value at address.
s points to address of location where 'k' is stored.
s+1 points to 1 byte after the base address 's' (since char stores 1 byte. If it were an int it would point to base address+4 bytes.
.
.
s+i points to base address + i bytes.
I have corrected your code.
#include <stdio.h>
void squeeze(char *s, int c);
int main(void){
char s[]="kyriacos";
squeeze(s,'c');
printf("the new kyriacos is %s",s);
}
void squeeze(char *s, int c){
int i,j;
for(i=j=0; *(s+i)!='\0';i++){//the error is here
//u need to access the value at address using * operator instead u were
//accessing only addresses
if(*(s+i)!=c){
*(s+j)=*(s+i);
j++;
}
}
*(s+j)='\0';
}
Also note that normally when u pass a char in an function it is received by the same data type.But since an int is used the char 'c' is converted into integer in this case 99 which is its ASCII value. So in loop where it compares whether the character is equal to c the machine also converts *(s+i) to an int value and compares both of them
The program stops working.
Even if I put only one int.
I tried many different ways but can't figure out what is wrong.
I am trying to take input of integers separated by space.
There can be any no of integers.
#include<stdio.h>
#include<stdlib.h>
int main(void) {
int i,j=0;
int b[100];
char a[100];
fgets(a,100,stdin);
for(i=0;i<strlen(a);i++)
{
b[i] = atoi(a[j]);
j=j+2;
}
for(i=0;i<strlen(b);i++)
{
printf("%d ",b[i]);
}
}
Here is the prototype of atoi you have to use a character array but you are sending a character only.atoi(str[i])
int atoi(const char *str)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int val;
char str[20];
strcpy(str, "98993489");
val = atoi(str);
printf("String value = %s, Int value = %d\n", str, val);
return(0);
}
Do the following:
for(i = 0; i < strlen(a); i += 2)
{
b[j] = a[i];
j++;
}
though atoi() accepts only a string argument or u can say constant char pointer and str[i] is nothing but a pointer pointing at a single character of the character array.
Therefore once we pass atoi(str[i]) , that means we are passing a character to the function, which will give an error.
Therefore you must pass the address of that particular character from where you want to convert the substring into a number i.e. atoi(&str[i]).
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.
this is my example code:
#include<stdio.h>
#include<string.h>
#include<ctype.h>
void convert(char *a, char *b) {
int i;
for(i=0; i<strlen(a); i++) {
b[i]=tolower(a[i]);
}
}
int main() {
char a[20], b[20];
fgets(a, sizeof(a), stdin);
convert(a, b);
printf("%s\n", b);
return 0;
}
but sometimes the convert() function convert also one more char than strlen(a) (it's a random char), for example this is an output:
ASDSA
asdsa
%
How can i fix it?
You have to add a nul character ('\0') at the end of b.
As others mentioned, you need to null-terminate the target string. Aside from that, note that you are recalculating the length of a at each iteration of the loop. This will not matter for small strings, but with large strings you will notice that the time to convert is proportional to the square of the string length. The standard idiom is to calculate the length once and use it repeatedly. With those two changes, the function would look like this:
void convert(const char *a, char *b) {
size_t i, len = strlen(a);
for(i = 0; i < len; i++) {
b[i] = tolower((unsigned char) a[i]);
}
b[len] = '\0';
}
strlen returns the length of the string, for instance strlen("hello") is 5.
This does not copy the 0 character used to terminate the string (which means the string in the memory is actually 6 characters long: 'h' 'e' 'l' 'l' 'o' '0')
So after a few years of inactivity after studying at uni, I'm trying to build up my c experience with a simple string reverser.
here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
*
*/
int main(int argc, char** argv) {
reverser();
return(0);
}
int reverser(){
printf("Please enter a String: ");
//return (0);
int len;
char input[10];
scanf("%s",&input);
int quit = strcmp(input,"quit");
if(quit == 0){
printf("%s\n","Program quitting");
return(0);
}
len = strlen(input);
printf("%i\n",len);
char reversed[len];
int count = 0;
while (count <= (len-1)){
//printf("%i\n",(len-count));
reversed[count] = input[(len-1)-count];
count++;
}
//printf("%s\n",input);
printf(reversed);
printf("\n");
reverser();
}
When I input "hello", you would expect "olleh" as the response, but I get "olleh:$a ca&#",
How do I just get the string input reversed and returned?
Bombalur
Add a '\0' at the end of the array. (as in, copy only chars until you reach '\0' - which is the point at array[strlen(array)], then when you're done, add a '\0' at the next character)
Strings are conventionally terminated by a zero byte. So it should be
char reversed[len+1];
And you should clear the last byte
reversed[len] = (char)0;
you forgot the \0 at the end of the string
This is because you are creating an array with size 10. When you take in some data into it (using scanf) and the array is not filled up completely, the printf from this array will give junk values in the memory. You should iterate for the length of the input by checking \n.
must have a size + 1 to string length so that you can have a \0 at the end of string that will solve your problem
The following is a (simple and minimal implementation of) string reverse program (obviously, error conditions, corner cases, blank spaces, wider character sets, etc has not been considered).
#include <stdio.h>
int strlen(char *s)
{
char *p = s;
while (*p)
p++;
return p - s;
}
char * strrev(char a[])
{
int i, j;
char temp;
for (i=0, j=strlen(a)-1 ; i<j ; i++, j--) {
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
return a;
}
int main()
{
char str[100];
printf("Enter string: ");
scanf("%s", str);
printf("The reverse is %s \n", strrev(str));
return 0;
}
Hope this helps!