Concatenate string with error - c

I have this code in C but I don't know why I get an error like Argument of type “char” is incompatible with parameter of type const char*
char number_string[size] = { NULL };
int counter = 0;
for (counter = 0; counter < strlen(input_string - 1); counter++)
{
temp = input_string[counter];
if (isdigit(temp))
{
strcat(number_string, temp); //temp variable has the error only in this line
}
}

You're mixing char and char *. The declaration of number_string[] might not warn you, because NULL may simply be defined as 0, which is legal as a char and as a pointer. But the variable temp is definately a problem: You don't show its declaration, but its first assignment makes it a char, and its second use in strcat assumes it is a char *.
If you want to add a single character at a time to a string, you'll have to do it by hand, something like this:
int nslen = strlen(number_string);
for ...
number_string[nslen++] = temp
number_string[nslen] = '\0';

char *strcat(char *dest, const char *src); expects its last argument to have type const char *
temp is a variable of type char.
So you're getting the error Argument of type “char” is incompatible with parameter of type const char*.
You could try something like this...
strncat(number_string, &temp, 1)
I usually favor something like...
sprintf (buffer, "%s%c", number_string, temp)

This is not an answer to your problem with types; it is a suggestion to tackle the problem in another way.
You want to fill a string with all numeric digits from the input string. There is no standard function to do this.
You could use strcat, but that function operates on strings, which must be zero-terminated. You could create a temporary string of two chars – one digit and one null-terminator – but that would be ineffective. strcat also requires you to ensure that you don't overflow the char buffer that you append to.
In cases like yours, it is usually easier to tackle the problem on a low level, where you create the char array yourself, one character at a time. For example, you can iterate through the input string with i and copy all digits to the number string by means of a second index, j:
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
int main()
{
size_t size = 12;
char number[size];
const char *input = "Alpha 123/Bravo 456/Charlie 789/Delta 007";
int i, j;
j = 0;
for (i = 0; input[i] != '\0'; i++) {
if (isdigit((unsigned char) input[i]) && j + 1 < size) {
number[j++] = input[i];
}
}
number[j] = '\0';
puts(number);
return 0;
}
Note how the code keeps track of the characters in the number string and how it takes care not to overflow the buffer. The number string may be truncated, but it will always be null-terminated.
I've also used input[i] != '\0' to detect the end of the string (which is, by definition, the null terminator '\0') instead of calling strlen(input), which always starts looking for the terminator fro the beginning of the string.

There are multiple problems in your code:
calling strlen(input_string - 1) most likely invokes undefined behaviour. You probably meant strlen(input_string) - 1 which would still cause the loop to run too far if input_string is an empty string;
calling strlen for each iteration is inefficient anyway;
calling isdigit(temp) is incorrect if temp is a char and char is signed by default;
strcat cannot be used the way you call it;
you should check for potential buffer overflow if all digits do not fit in the destination array.
Here is a much simpler function to extract all digits from the input_string:
char number_string[size];
int i, j;
for (i = j = 0; input_string[i] != '\0'; i++) {
unsigned char uc = input_string[i];
if (j < size - 1 && isdigit(uc)) {
number_string[j++] = uc;
}
}
number_string[j] = '\0';

Related

c function convert "fffoootoo" to "foto" (leaves out following repeating characters)

The task would be to remove following characters that are repeating from a char array, like "deeeciddeee" -> "decide" or "phhhonne" -> "phone".
I have a function that crashes the console, and I can't spot the bug:
char* my_unique(char *first, char *last) {
char* ret=first;
for(int i=0; first+i!=last; i++){
if(first[i]==first[i+1]){
for(int j=i; first+j!=last; j++)
first[j]=first[j+1];
last--;
}
}
return ret;
}
it is called this way:
char* a="oooat";
a=my_unique(a, a+strlen(a));
cout<<a;
please help me!
Besides a small bug (you should add the line i--; after last--;, because you're deleting the character at possition i, so what has been the character at i+1 became the new character at possition i. If you don't decrease i, it will be increased and you jump over a character) the code runs perfectly fine IF it is called with
const char* b = "oooat";
char* a = new char[strlen(b) + 1];
for (size_t c = 0; c < strlen(a) + 1; c++) { a[c] = b[c]; }
a = my_unique(a, a + strlen(a));
cout << a;
delete[] a;
Notice that I've used a edit-able copy of the string, as the literal itself is of type const char* and therefor can't be changed at all. And as I said, this works perfectly fine and prints "oat", just as expected, without any crash. So your problem might be that you try to edit a const string literal? In that case you might consider to copy it, as I did, or use std::string (if you code in C++).
There are many beginner mistakes in the code.
Let me point you one by one.
char* a="oooat";
a=my_unique(a, a+strlen(a));
cout<<a;
When you declare a string like this : char* a="oooat", a is a string literal. The memory for the string is allocated into text section of the program. Which basically means you cannot modify the values inside the strings. You can only read from them. Hence when you are passing pointer a to the function and modifying it, it will result in segmentation fault(Illegal access to memory).
Why do you need a ret pointer here? char* ret=first;
You are passing a pointer and modifying the value inside it. Hence the new data will be reflected in the calling function and we need not return it explicitly. So, it is redundant.
Overall logic can be simplified as well
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MYSTR "ooooat"
void my_unique(char *first, char *last) {
int size = last - first;
int i = 0, j = 0, k = 0;
for (; i < size; i++, j++) {
first[j] = first[i];
// Continue to check how many repetitions are there
while (i + 1 < size && (first[i] == first[i+1])) i++;
}
// In the end terminate the string with a NULL.
first[j] = '\0';
return;
}
int main()
{
char a[] = MYSTR;
my_unique(a, a+strlen(a));
printf("%s", a);
return 0;
}
This is in C. There are simpler ways of doing this in C++, and the code can definitely be condensed but has been left simpler for readability.
#include <stdlib.h>
char* fix(char *input) {
char *lookahead = input;
char *newchar, *ret;
// Determine Max Return String Length
int len = 0;
while (*lookahead != '\0') {
len++;
lookahead++;
};
// allocate max possible memory needed and set the pointers
ret = malloc(len);
newchar = ret;
lookahead = input;
*newchar = *lookahead; // copy the first character
while (*lookahead != 0) {
lookahead++; // incrementing this ptr first starts lookahead at 2nd character and
// ensures the null terminator gets copied before the while loop ends
if (*newchar != *lookahead) { // only copy new characters to new return string
newchar++;
*newchar = *lookahead;
};
};
return ret;
};
I'll try to give my answer so that it makes the as little changes as possible to your original code, while using the simplest methods.
The main problem has already been identified by the previous comments - you cannot alter a string literal.
Also, the line of code
i--;
has to be placed as well, with the reason well clarified above.
While making an editable version of the string may be a good way of fixing the problem, a more straightforward way would be to make it a local string, as such :
char b[] = "oooat";
but doing this will make it incompatible with the return type of your my_unique function (char*). But why would you need a return type in the first place, if you are fixing the string itself?
My final code would look like this :
void my_unique(char *first, char *last) {
char* ret=first;
for(int i=0; first+i!=last; i++){
if(first[i]==first[i+1]){
for(int j=i; first+j!=last; j++)
first[j]=first[j+1];
last--;
i--;
}
}
}
making the function return void.
Hope this helps.

Capitalizing all copies of a word: why does this code fail when it's in its own function?

I have two C-style strings:
char st[100] = "to be or not to be ";
char sub_s[100] = "be";
I need to find the beginning of the "be" with strstr(st, sub_s) and change it to capital letters. The new string needs to be `"to BE or not to BE ";
I manage to do it with out the function like so:
void main()
{
char st[100] = "to be or not to be ";
char sub_s[100] = "be";
char* p;
int i;
while (p = strstr(st, sub_s))
{
for (i = 0; i < strlen(sub_s); i++)
{
p[i] -= 32;
}
}
printf("%s\n", st);
}
But when I put this code into its own function it doesn't work any more:
void main()
{
char st[100] = "to be or not to be ";
char sub_s[100] = "be";
replaceSubstring(st, sub_s);
}
void replaceSubstring(char* str, char* substr)
{
int* p;
int i;
while (p = strstr(str, substr))
{
for (i = 0; i < strlen(substr); i++)
{
p[i] -= 32;
}
}
printf("%s\n", st);
}
What's going on here?
In the function that you've written, you've set the type of p to be an int*, not a char *. This means when you write
p[i] -= 32;
the compiler will assume each element pointed at by p is an int and therefore take a step of size sizeof(int) in memory rather than a step of size 1 in memory. In other words, the code is interpreted as
Start at the location pointed at by p.
Jump forward i * sizeof(int) bytes.
Read an integer value from that location.
Subtract 32 from it.
Write it back
rather than
Start at the location pointed at by p.
Find the character i steps down from there.
Subtract 32 from that character.
To fix this, change the type of p to be char*, not int*.
This is the sort of error that would likely be easily detected if you cranked the compiler warning level up to maximum. I would strongly recommend doing that when you're learning to code, then asking questions about the warnings you get when you don't understand them.
Some other stray notes:
The return type of main should be int, not void.
Rather than subtracting 32 from each character, which works but isn't the clearest thing in the word, consider using the tolower function from the <ctype.h> header.
If the substring you're searching for consists solely of non-letter characters (say, ":-)"), then this code can cause an infinite loop. Do you see why? Think about how you might fix it.

Appending char to C array

I have a string declared as such:
char *mode_s = (char *)calloc(MODE_S_LEN, sizeof(char));
How can I add a char to the end of the array?
Lets assume " first available position " means at index 0.
char *mode_s = (char *)calloc(MODE_S_LEN, sizeof(char));
*mode_s='a';
To store a character at an arbitrary index n
*(mode_s+n)='b';
Use pointer algebra, as demonstrated above, which is equivalent to
mode_s[n]='b';
One sees that the first case simply means that n=0.
If you wish to eliminate incrementing the counter, as specified in the comment bellow, you can write a data structure and a supporting function that fits your needs. A simple one would be
typedef struct modeA{
int size;
int index;
char *mode_s;
}modeA;
The supporting function could be
int add(modeA* a, char toAdd){
if(a->size==a->index) return -1;
a->mode_s[index]=toAdd;
a->index++;
return 0;
}
It returns 0 when the add was successful, and -1 when one runs out of space.
Other functions you might need can be coded in a similar manner. Note that as C is not object oriented, the data structure has to be passed to the function as a parameter.
Finally you code code a function creating an instance
modeA genModeA(int size){
modeA tmp;
tmp.mode_s=(char *)calloc(size, sizeof(char));
tmp.size=size;
tmp.index=0;
return tmp;
}
Thus using it with no need to manually increment the counter
modeA tmp=genModeA(MODE_S_LEN);
add(&tmp,'c');
There is no standard function to concatenate a character to a string in C. You can easily define such a function:
#include <string.h>
char *strcatc(char *str, char c) {
size_t len = strlen(str);
str[len++] = c;
str[len] = '\0';
return str;
}
This function only works if str is allocated or defined with a larger size than its length + 1, ie if there is available space at its end. In your example, mode_s is allocated with a size of MODE_S_LEN, so you can put MODE_S_LEN-1 chars into it:
char *mode_s = calloc(MODE_S_LEN, sizeof(*mode_s));
for (int i = 0; i < MODE_S_LEN - 1; i++) {
strcatc(mode_s, 'X');
}
char newchar = 'a'; //or getch() from keyboard
//realloc memory:
char *mode_sNew = (char *)calloc(MODE_S_LEN + 1, sizeof(char));
//copy the str:
srncpy(mode_sNew, mode_s, MODE_S_LEN);
//put your char:
mode_sNew[MODE_S_LEN] = newchar;
//free old memory:
free(mode_s);
//reassign to the old string:
mode_s = mode_sNew;
//in a loop you can add as many characters as you want. You also can add more than one character at once, but assign only one in a new position

C: reverse string function not affecting pointer

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int reverse(char *, int);
main()
{
char *word = "Thanks for your help";
reverse(word, strlen(word));
printf("%s", word);
getchar();
}
int reverse(char *line, int len)
{
int i, j;
char *newline = malloc(strlen(line));
for (i = len - 1, j = 0 ; i >= 0; i--, j++)
{
newline[j] = line[i];
}
newline[j] = '\0';
line = &newline;
}
Hey folks. I've got a simple C question that I can't seem to solve.
The program above is meant to take in a string and print it out backwards. Reverse is the function by which this is done.
The issue, specifically, is that when I print word in main(), the string appears unchanged. I've attempted to make the address of line the address of newline, but it doesn't have any effect.
int reverse(char *line, int len)
{
int i, j;
char *newline = malloc(strlen(line));
for (i = len - 1, j = 0 ; i >= 0; i--, j++)
{
newline[j] = line[i];
}
newline[j] = '\0';
line = &newline; // Your problem is here
}
You're merely assigning to the local line pointer. This has no effect on the calling function whatsoever.
Consider instead:
char *reverse(char *line, int len)
{
// ...
return newline;
}
Additional advice:
Turn on compiler warnings, and heed them. You've got lots of little things wrong (e.g. reverse isn't currently returning anything, but is declared as returning int).
Given that the first argument of reverse is a pointer to a C string (NUL-terminated), there's no need to take a length argument as well.
A reverse function doesn't necessarily need to be defined as returning a copy of the string, reversed. It could instead reverse a string in-place. Note that you cannot pass a string literal to a function like this, as they are read-only.
Here's how I would write this:
#include <stdio.h>
#include <string.h>
void reverse(char *str)
{
size_t i, j;
for (i = strlen(str) - 1, j = 0 ; i > j; i--, j++)
{
// Swap characters
char c = str[i];
str[i] = str[j];
str[j] = c;
}
}
int main(void)
{
// Mutable string allocated on the stack;
// we cannot just pass a string literal to reverse().
char str[] = "Here is a test string";
reverse(str);
printf("Result: \"%s\"\n", str);
return 0;
}
Note that the for loop condition is i > j, because we want each to only traverse half the array, and not swap each character twice.
Result:
$ ./a.exe
Result: "gnirts tset a si ereH"
Take a look at the code below:
void addOne(int a) {
int newA = a + 1;
a = newA;
}
int main() {
int num = 5;
addOne(num);
printf("%d\n", num);
}
Do you see why that will print 5, and not 6? It's because when you pass num to addOne, you actually make a copy of num. When addOne changes a to newA, it is changing the copy (called a), not the original variable, num. C has pass-by-value semantics.
Your code suffers from the same problem (and a couple other things). When you call reverse, a copy of word is made (not a copy of the string, but a copy of the character pointer, which points to the string). When you change line to point to your new string, newLine, you are not actually changing the passed-in pointer; you are changing the copy of the pointer.
So, how should you implement reverse? It depends: there are a couple options.
reverse could return a newly allocated string containing the original string, reversed. In this case, your function signature would be char *reverse, instead of int reverse.
reverse could modify the original string in place. That is, you never allocate a new string, and simply move the characters of the original string around. This works, in general, but not in your case because char pointers initialized with string literals do not necessarily point to writable memory.
reverse could actually change the passed-in pointer to point at a new string (what you are trying to do in your current code). To do this, you'd have to write a function void reverse(char **pointerToString). Then you could assign *pointerToString = newLine;. But this is not great practice. The original passed-in argument is now inaccessible, and if it was malloc'd, it can't be freed.

C function to capitalize first letter of words in an array

I'm pretty new to C and am hitting a wall when creating the below function. I want to use this function to make the first letter of a word upper case for a static character array (char string[]. It looks ok to my eye, but I'm getting some syntax errors which are probably pretty basic.
compiler errors:
error: invalid conversion from const char' toconst char*'
initializing argument 1 of `size_t strlen(const char*)'
assignment of read-only location
void Cap(char string[]){
int i;
int x = strlen(string);
for (i=1;i<x;i++){
if (isalpha(string[i]) && string[i-1] == ' '){
// only first letters of a word.
string[i]= toupper(string[i]);
}if (isalpha(string[0]))
{
string[0]=toupper(string[0]);
}
}
}
you might want to run strlen(string) - as strlen(string[i]) is trying to get the length of a single char.
I will also point out your braces don't match ...
if (isalpha(string[i])){
string[i]= toupper(string[i]);
Remove brace on the if line or put a close brace after your assigning statement.
I took your code and tried to compile it. Well, it would be nice to see compilable code the next time. Here is one with comments.
#include <stdio.h> // Now I am able to use printf.
#include <string.h> // I was not able to use strlen without this...
void Cap(char string[]){
int i;
int x = strlen(string); // You want to get the length of the whole string.
for (i=1;i<x;i++){
if (isalpha(string[i]) && string[i-1] == ' '){
// only first letters of a word.
string[i]= toupper(string[i]);
}
}
}
main(){
char string[] = "text with lowercase words.";
Cap(string);
printf("%s",string);
};
Still the first word of the text is lowercase. This is a task for you.
You're missing the closing curly brace for your if statement. This might just be a typo in the question, but mentioning it just in case.
Your function is declared void. This means it returns nothing. Any return statement should have nothing after the word since the function returns nothing, and in many cases you won't have a return statement at all.
However, the biggest issue is that this isn't an array of strings. It's an array of chars, which is just one string. char* string and char string[] both (potentially) refer to an array of characters, which makes up a single string. You would need to use another level of indirection to refer to an array of array of characters: char** strings, char* strings[], or char strings[][]. The last form would require you specify how long all the strings could be, so you'd usually only use the first two.
The problem here is that you are passing in a single string, not an array of strings.
Basically in C, a string is an array of chars, hence an array of strings is a two dimensional array like so:
const char* strings[];
There are a few other issues with the code. You haven't initialized i before using it.
A alternate approach: (write a function)
1) (optional) Allocate memory for new buffer of same length for results in calling function.
2) In function - Set first char of new string to upper case version of original string
3) Walk through the string searching for spaces.
4) For each space, Set next char of new string to upper case of char in original string
5) Loop on 4) until NULL detected
6) Free any allocated memory in calling program.
Code example:
void capitalize(char *str, char *new)
{
int i=0;
new[i] = toupper(str[0]);//first char to upper case
i++;//increment after every look
while(str[i] != '\0')
{
if(isspace(str[i]))
{
new[i] = str[i];
new[i+1] = toupper(str[i+1]);//set char after space to upper case
i+=2;//look twice, increment twice
}
else
{
new[i] = str[i];//for no-space-found, just copy char to new string
i++;//increment after every look
}
}
}
This should work just fine.
#include <stdio.h>
#include <string.h>
capital(char s[])
{
int i;
for(i=0; i<strlen(s); i++)
{
if (i==0||s[i-1]==' '&&s[i]>='a'&&s[i]<='z')
s[i]=toupper(s[i]);
}
puts(s);
}
main()
{
char s[100];
printf("Enter a line: ");
gets(s);
capital(s);
}
I made an update based on Stefan Bollmann answer:
#include <string.h>
#include <stdio.h>
char* uc_words(char string[])
{
int i;
int x = strlen(string);
int counter = 0;
for (i = 0; i < x; i++)
{
// If found a white-space reset counter
if (isspace(string[i]))
counter = 0;
// Check if first character in word
if (isalpha(string[i]) && !isspace(string[i]) && counter == 0)
{
string[i]= toupper(string[i]);
counter = 1;
}
}
return string;
}
int main()
{
char string[] = "hello world";
printf("%s\n", uc_words(string));
return 0;
}

Resources