Trying to remove all numbers from a string in C - c

I'm trying to take all of the numbers out of a string (char*)...
Here's what I have right now:
// Take numbers out of username if they exist - don't care about these
char * newStr;
strtoul(user, &newStr, 10);
user = newStr;
My understanding is that strtoul is supposed to convert a string to an unsigned long. The characters that are not numbers are put into the passed in pointer (the 2nd arg). When i reassign user to newStr and print it, the string remains unchanged. Why is this? Does anyone know of a better method?
From the documentation example:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char str[30] = "2030300 This is test";
char *ptr;
long ret;
ret = strtoul(str, &ptr, 10);
printf("The number(unsigned long integer) is %lu\n", ret);
printf("String part is |%s|", ptr);
return(0);
}
Let us compile and run the above program, this will produce the following result:
The number(unsigned long integer) is 2030300
String part is | This is test|

char* RemoveDigits(char* input)
{
char* dest = input;
char* src = input;
while(*src)
{
if (isdigit(*src)) { src++; continue; }
*dest++ = *src++;
}
*dest = '\0';
return input;
}
Test:
int main(void)
{
char inText[] = "123 Mickey 456";
printf("The result is %s\n", RemoveDigits(inText));
// Expected Output: " Mickey "
}
The numbers were removed.

Here is a C program to remove digits from a string without using inbuilt functions. The string is shifted left to overwrite the digits:
#include <stdio.h>
int main(void) {
char a[] = "stack123overflow";
int i, j;
for (i = 0; a[i] != '\0'; i ++) {
if (a[i] == '0' || a[i] == '1' || a[i] == '2' || a[i] == '3' || a[i] == '4' || a[i] == '5' || a[i] == '6' || a[i] == '7' || a[i] == '8' || a[i] == '9') {
for (j = i; a[j] != '\0'; j ++)
a[j] = a[j + 1];
i--;
}
}
printf("%s", a);
return 0;
}
Example of execution:
$ gcc shift_str.c -o shift_str
$ ./shift_str
stackoverflow

strtoul() does not extract all numbers from string, it just trying to covert string to number and convertion stops when non digit is find. So if your string starts from number strtoul() works as you expect, but if string starts from letters, strtoul() stops at the first symbol. To solve your task in simple way you should copy all non-digits to other string, that will be a result.

The problem you are having is that strtoul is converting characters at the beginning of the string into an unsigned long. Once it encounters non-numeric digits, it stops.
The second parameter is a pointer into the original character buffer, pointing at the first non-numeric character.
http://www.cplusplus.com/reference/cstdlib/strtoul/
Parameter 2 : Reference to an object of type char*, whose value is set by the function to the next character in str after the numerical value.
So, if you tried to run the function on "123abc567efg" the returned value would be 123. The original string buffer would still be "123abc567efg" with the second parameter now pointing at the character 'a' in that buffer. That is, the pointer (ptr) will have a value 3 greater than original buffer pointer (str). Printing the string ptr, would give you "abc567efg" as it simply points back into the original buffer.
To actually remove ALL the digits from the string in C you would need to do something similar to this answer : Removing spaces and special characters from string
You build your allowable function to return false on 0-9 and true otherwise. Loop through and copy out digits to a new buffer.

Related

how to fix this code so that it can test the integers present next to the character?

Given a string containing alphanumeric characters, calculate the sum of all numbers present in the string.
The problem with my code is that it displays the integers present before the characters, but it is not summing up the integers after the characters.
The execution is easy in python and C++ but I cant get it done using C! Can anyone please verify where I have done wrong? << thank you !
enter code here
#include<stdio.h>
#include<string.h>
int convert(char[]);
int main()
{
char ch[100],temp[100]={0};
int i=0,s=0,j=0,n;
scanf("%s",ch);
for(i=0;i<strlen(ch);i++)
{
if((ch[i]>='0') && (ch[i]<='9'))
{
temp[j]=ch[i];
j++;
}
else
{
if(temp[0]== '\0')
{
continue;
}
else
{
n=convert(temp);
s+=n;
temp[0]= '\0';
j=0;
}
}
}
printf("%d",s);
return 0;
}
int convert(char s[]) //converting string to integer
{
int n=0;
for(int i=0;i<strlen(s);i++)
{
n= n * 10 + s[i] - '0';
}
return n;
}
Input : 12abcd4
Expected output : 16
But the output is 12 for my code.
There are two problems in your code. The first was mentioned in the comments : if the last character is a digit, the last "number section" will not be taken into account. But I don't think that the solution given in the comments is good because if the last character is not a digit, you will have a wrong value. To correct this, I added an if statement that check if the last character is a digit, if so call convert().
The second problem is that strlen return the number of characters in you string from the beginning until it finds an '\0'. The way you used your string lead to the follow problem :
ch = "12abcd4".
At first you have temp = '1' + '2' + '\0'...
After calling convert() you set temp[0] to '\0', thus temp = '\0' + '2' + '\0'... .
And when you start reading digit again, you set '4' in temp[0]. Your string is now : '4' + '2' + '\0'... .
The n returned will be 42 and your result 54 (12+42). There are several solution to have the expected behavior, I chose to use your variable j to indicate how many characters should be read instead of using strlen() :
#include<stdio.h>
#include<string.h>
int convert(char[], int size);
int main() {
char ch[100],temp[100]={0};
int i=0,s=0,j=0,n;
scanf("%s",ch);
for(i=0;i<strlen(ch);i++) {
if((ch[i]>='0') && (ch[i]<='9')) {
temp[j]=ch[i];
j++;
// change here
if(i == strlen(ch) - 1) {
n=convert(temp, j);
s+=n;
}
}
else {
// change here
n=convert(temp, j);
s+=n;
if(temp[0]== '\0') {
continue;
}
temp[0]= '\0';
j=0;
}
}
printf("%d\n",s);
return 0;
}
//change here
int convert(char s[], int size) {
int n=0;
for(int i=0;i<size;i++) {
n= n * 10 + s[i] - '0';
}
return n;
}
You could use a combination of strtoul() and strpbrk() to do this.
Declare two character pointers start_ptr and end_ptr and make start_ptr point to the beginning of the string under consideration.
char *start_ptr=s, *end_ptr;
where s is the character array of size 100 holding the string.
Since your string has only alphanumeric characters, there is no - sign and hence there are no negative numbers. So we can get away with using unsigned integers.
We are using strtoul() from stdlib.h to perform the string to integer conversion. So let's declare two variables: rv for holding the value returned by strtoul() and sum to hold the sum of numbers.
unsigned long rv, sum_val=0;
Now use a loop:
for(; start_ptr!=NULL; )
{
rv = strtoul(start_ptr, &end_ptr, 10);
if(rv==ULONG_MAX && errno==ERANGE)
{
//out of range!
printf("\nOut of range.");
break;
}
else
{
printf("\n%lu", rv);
sum_val += rv;
start_ptr=strpbrk(end_ptr, "0123456789");
}
}
strtoul() will convert as much part of the string as possible and then make end_ptr point to the first character of the part of the string that could not be converted.
It will return ULONG_MAX if the number is too big and errno would be set to ERANGE.
Otherwise the converted number is returned.
strpbrk() would search for a set of characters (in this case the characters 0-9) and return a pointer to the first match. Otherwise NULL is returned.
Don't forget to include the following header files:
stdlib.h ---> strtoul
string.h ---> strpbrk
limits.h ---> ULONG_MAX
errno.h ---> errno
In short, we could make the program to something like
for(; start_ptr!=NULL; sum_val += rv, start_ptr=strpbrk(end_ptr, "0123456789"))
{
rv = strtoul(start_ptr, &end_ptr, 10);
if(rv==ULONG_MAX && errno==ERANGE)
{
//out of range!
break;
}
}
printf("\n\n%lu", sum_val);
So the value of sum_val for the string "12abcd4" would be 16.
scanf() is usually not the best way to accept input that is not well-formatted. Maybe you can use fgets()-sscanf() combo instead.
If you must use scanf(), make sure that you check the value returned by it, which in your case must be 1 (the number of successful assignments that scanf() made).
And to prevent overflow, use a width specifier as in
scanf("%99s",ch);
instead of
scanf("%s",ch);
as 100 is the size of the ch character array and we need one extra byte to store the string delimiter (the \0 character).

Run length encode in C, Problem with strcat

I'm trying to write a run-length encoding program in C.
For the input 'ABBCD' I expect the following result: 'A1B2C1D1'
I hand over a two-dimensional char array line for line to the function that encodes the characters:
for(i; i <= curline; i++) //hand over line for line
{
encoded->lines[i] = malloc(255);
encoded->lines[i] = rle_encode(read->lines[i]); //read->lines contains the characters of each line
printf("%s", encoded->lines[i]); // print out the result returned by the function rle_encode
}
I have tested this and know that it would work.
Now this is my function rle_encode:
char *rle_encode(char *line){
char *encode = malloc(sizeof(2 * strlen(line) + 1));
char prev = line[0]; //here I want to save the previous character
int i = 0;
int z = 1;
do{
i++;
if(prev == line[i]) // if character n equals n-1 (previous)
{
z++; // increase counter varaible z
}else
{
strcat( encode, line[i] ); //the content of line[i] will be append to the array encode
strcat( encode, z ); //also the counter variable will be appended
}
prev = line[i];
}while(line[i] != '\n'); //in the end of each line a '\n' appears, if line[i] is '\n' it should stop the function
return encode;}
What is wrong in function rle_encode?
malloc(sizeof(encode))
sizeof(encode) is the size of a pointer, so you allocate for it only 4 or 8 bytes.
I think that you also have to start the counters i and z from 0, not from 1.
EDIT:
There are many problems, I did not mark them all.
This is not a complete answer to your question because there are many other issues in your code.
This small program shows how to append a char to a string and how to append the decimal representation of an int to a string.
#include <stdio.h>
#include <string.h>
int main(void)
{
char encode[100] = "abc";
printf("%s\n", encode);
// append the char 'X' to the encode string
int len = strlen(encode);
encode[len] = 'X';
encode[len + 1] = 0; // put the NUL terminator
printf("%s\n", encode);
// append the decimal representation of the int y to encode
int y = 123;
char *p = encode + strlen(encode);
sprintf(p, "%d", y);
printf("%s\n", encode);
}
Output:
abc
abcX
abcX123
You really need to learn the basics of C.

How to do read multiple characters from an argument

I am trying to read multiple characters from an argument in c. So when the person rules the file like "./amazing_program qwertyyuiopasdfghjklzxcvbnm" it would read the qwerty characters and store the, into a array as a number (ASCII) like:
array[0] = 'q';
array[1] = 'w';
array[2] = 'e';
array[3] = 'r';
array[4] = 't';
array[5] = 'y';
and so on...
My goal: Is to separate the argument into each individual character and store each individual character into a different place in the array (like shown above).
I tried this way, but it didn't work.
int user_sub = 0;
int argument = 1;
while (argument < argc) {
user_sub = atoi(argv[argument]);
argument = argument + 1;
}
From reading your comments, I've come to understand you just want to be able to get to the characters so you can do a shift. Well, that's not so hard to do, so I've tried to show you how you can do it here without having to complete the Caesar logic for you.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SHIFT 13
int main (int argc, const char *argv[]) {
// Verify they gave exactly one input string.
if (argc != 2) {
fprintf(stderr, "Usage: %s <word>\n", argv[0]);
exit(EXIT_FAILURE);
}
// A string IS already an array of characters. So shift then and output.
int n = strlen(argv[1]);
for (int i = 0; i < n; i++) {
char c = argv[1][i];
// Shift logic here: putchar(...);
printf("%d: %c\n", i, c);
}
return EXIT_SUCCESS;
}
The key takeaway is that a string is already an array. You don't need to make a new array and stick all the characters in it. You already have one. What this program does is simply "extract" and print them for you so you can see this. It currently only writes the current argument string to output, and does no shifting. That's for you to do. It also doesn't take into account non-alphabetical characters. You'll have to think about them yourself.
You have serious lack :
1)
A string in C is an ARRAY of type char. We know where the end of the array is thank to a special value : '\0'.
Now, you have to deeply understand that each case of the array contain a NUMBER : since the type of the case is char, it will be a number in the range [-128, 127] (yeah, I know that char is special and can be signed or not, but let's keep it simple for the time being).
So if you acces each case of the array and print it, you will have a number between -128 and 127. So how the program know to print a letter instead of a number ? And how do he know which letter for which number ?
Thank to an internal table used for this uniq purpose. The most common is the ASCII table. So if a case of the array is 65, what will be printed is 'A'.
2) How can I go through each case of a string ? (which is an array of char terminated by '\0') ?
Simply with a for loop.
char str[] = "test example";
for (size_t i = 0; str[i] != '\0'; ++i) {
printf("The %d letter is '%c'\n", i, str[i]);
}
Again, since it's a number in str[i], how the program know how to print a letter ? Thank to the "%c" in printf, meaning "print the letter using the table (probably ASCII)". If you use "%s", it's the same thing, but you have to give the array itself instead of a case of the array.
So, what if I want to print the number instead of the letter ? Just use "%d" in printf.
char str[] = "test example";
for (size_t i = 0; str[i] != '\0'; ++i) {
printf("The %d letter is '%c' and it's real value is %d\n", i, str[i], str[i]);
}
Now, what if we increment all the value in each case of the string ?
char str[] = "test example";
for (size_t i = 0; str[i] != '\0'; ++i) {
str[i] = str[i] + 1; // Or ++str[i];
}
for (size_t i = 0; str[i] != '\0'; ++i) {
printf("The %d letter is '%c' and it's real value is %d\n", i, str[i], str[i]);
}
We have changed the string "test example" into "uftu fybnqmf".
Now, for your problem, you have to take the resolution step by step :
First, make a function that alter (cypher) a string given in argument by adding a shift.
void CesarCypherString(char *string);
Beware of "overflow" ! If I want to have a shift of 5, then 'a' will become 'f', but what happen for 'z' ? It should be 'e'.
But if you look at the ascii table, 'a' = 97, 'f' = 102 (and it make sense, since 'a' + 5 = 'f', 97 + 5 = 102), but 'z' is 122 and 'e' is 101. So you cannot directly do 'z' + 5 = 'e' since it's wrong.
Hint : use modulo operator (%).
Next, when you have finished to do the function CesarCypherString, do the function CesarDecypherString that will decypher a string.
When you have finished, then you can concentrate on how to read/duplicate a string from argv.

C: Comparing hash value seems to disappear

For the love of holy code, I am trying to compare hashes to find the correct password. I am given a hash as a command line argument, and I then hash words from "a" to "ZZZZ" until one of the hash pairs match.
void decipher(string hash)
{
//Set the password, and the salt.
char pass[4] = "a";
char salt[] ="50";
//Compare the crypted pass againts the hash until found.
while (strcmp(hash,crypt(pass, salt)) != 0)
{
//Use int i to hold position, and return next char
int i = 0;
pass[i] = get_next(pass[i]);
tick_over (pass, i);
//Hardcode in a fail safe max length: exit.
if (strlen(pass) > 4)
{
break;
}
}
printf("%s\n", pass);
}
The problem is that it will not 'catch' the correct password / comparison, when that password is 4 letters long. It works for 1,2 and 3 letter long words.
//Tick over casino style
string tick_over (string pass, int i)
{
//Once a char reaches 'Z', move the next char in line up one value.
char a[] = "a";
if (pass[i] == 'Z')
{
if (strlen(pass) < i+2)
{
strncat (pass, &a[0], 1);
return pass;
}
pass[i+1] = get_next(pass[i+1]);
//Recursively run again, moving along the string as necessary
tick_over (pass, i+1);
}
return pass;
}
//Give the next character in the sequence of available characters
char get_next (char y)
{
if (y == 'z')
{
return 'A';
}
else if (y == 'Z')
{
return 'a';
}
else
{
return y + 1;
}
}
It does iterate through the correct word, as I have found in debugging. I have tried moving the
strcmp(hash, crypt(pass, salt)) == 0
into a nested if statement among other things, but it doesn't seem to be the problem. Is c somehow 'forgetting' the command line value? When debugging the hash value seemed to have disappeared :/ Please help!
char pass[4] = "a"; you're defining a char array which can contain at most 3 chars + null terminator.
that's not coherent with your "safety" test: if (strlen(pass) > 4)
When strlen is 4 the array is already overwriting something in memory because of the null termination char: undefined behaviour.
Quickfix: char pass[5] ...
Here is the explanation of the function strncat:
Append characters from string
Appends the first num characters of source to destination, plus a terminating null-character.
with a size of 4 you are not considering the terminating null character of your four chars array.

Converting string to number in C

I'm trying to write a program which converts lower cased alphabet to numerical digits.
a -> 01
b -> 02
...
z -> 26
For the first nine letters I need to put a 0 before the number.
This is my code.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAXLEN 128
void s2n(char str[])
{
int i;
char x;
char result[256];
for (i=0; str[i] != '\0'; i++) {
x = str[i];
x = x - 96;
if (x < 10) {
char src[2] = {0, x};
strcat(result, src);
}
else {
char src2[1] = {x};
strcat(result, src2);
}
printf("%s", result);
}
}
int main(void)
{
char str[MAXLEN];
printf("Lower cased string please: ", MAXLEN);
scanf("%s", str);
s2n(str);
return 0;
}
Could you tell me what is wrong with my code??
One problem I see is:
char src[2] = {0, x};
You want to use the character 0, rather than the byte value 0 (NUL):
char src[2] = {'0', x};
Also, you need to NUL terminate your src array:
char src[] = {'0', x, 0};
The NUL termination would need to be done in both cases.
Another problem is your x = x - 96 statement also does not take into account that the character 0 is different from the byte value 0. So
x = x - 96 + '0';
would be better.
You use strcat() on an uninitialized array, result, it doesn't work that way, strcat() looks for the terminating nul byte in it's first parameter, and glues the second parameter from that point.
In your case there is no '\0' in result, calling strcat() with result as the first parameter causes undefined behavior.
You should at least ensure that there is one '\0' in result, you can do that by just setting the first element of result to '\0', like
result[0] = '\0';
Right before the loop starts, also you pass the second paramter src which is an array but is not a string, because it has no terminating '\0', but you actually don't need an array nor strcat().
You can use an index variable and just assing the ith element of the array to the actual character computed from the original value, like
result[i] = x;
Then you don't nul terminate result, which causes undefined behavior when you try to print resutl.
You also passing a parameter to printf() where it's not expecting one, that indicates that you are either silencing or ignoring compiler warnings.
There are many problems in your code, the following code, does what you want
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void s2n(char chr)
{
char result[4];
if (snprintf(result, sizeof(result), "%02d", 1 + chr - 'a') >= sizeof(result))
return;
printf("%s", result);
}
int main(void)
{
char chr;
printf("Lower cased string please: ");
if (scanf(" %c", &chr) != 1)
{
fprintf(stderr, "input error!\n");
return -1;
}
s2n(chr);
return 0;
}
note that no strings are required except the one where you are going to store the result, which you can build easily with sprintf().

Resources