Concatenating an int to a string or converting in C - c

Im looking for a 6 digit random number on the end of foo-, I have been trying for a few hours now with no success. only error messages
note: expected 'char *' but argument is of type 'int'
Ive tried to convert the int to char but it just doesn't like it, My code is below,
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
char* concat(char *s1, char *s2)
{
char *result = malloc(strlen(s1)+strlen(s2)+1);//+1 for the zero-terminator
//in real code you would check for errors in malloc here
strcpy(result, s1);
strcat(result, s2);
return result;
}
int main ()
{
srand(time(NULL));
int r = rand();
printf(concat("foo-", r));
return 0;
}

You could do this
printf("foo-%d", r);
or
char buffer[10];
sprintf(buffer, "%d", r);
char *c = concat("foo-", r);
printf("%s", c);
free(c);
This will use your function. Please read the manual pages for sprintf and printf

for example:
srand(time(NULL));
int r = rand();
char* str = (char*)malloc(sizeof(char)*20);
snprintf(str, 7, "%d", r);
if (strlen(str) < 6) { /* if r had less than 6 digits */
sprintf(str, "%06d", r);
}
char* s = concat("foo-", str);
printf("%s",s);
free(str);
free(s);
return 0;
from http://joequery.me/code/snprintf-c/ :
int snprintf(char *str, size_t size, const char *format, ...);
str is the buffer where printf output will be redirected to. size is the maximum number of bytes(characters) that will be written to the
buffer, including the terminating null character that snprintf
automatically places for you. The format and the optional ...
arguments are just the string formats like "%d", myint as seen in
printf.
so, in order to get a 6 digit number converted, you specify in snprintf() the size argument to 7 (you include a null character).
sprintf() function sends formatted output to a string pointed to by the first argument (in our case this is str). %06d format provides that to str at least 6 digits will be sent.
CONCLUSION
you want to convert a 6 digit number to a char array. if the number had at least 6 digits, with snprintf() you will get the first 6 digits of the number that was converted. if it has less than 6 digits, the sprintf() will add zeroes at the beginning until there are 6 digits. so, if r = 101; the result would be 000101.
note that with your usage of concat function:
printf(concat("foo-",r));
compiler warns about (gcc in my case):
warning: format not a string literal and no format arguments
[-Wformat-security]
printf() function needs to know the format of the string argument that is passed. there's a nice answer about it right here : warning: format not a string literal and no format arguments

In the example I'm using sprintf to convert int to char[]. Also I'm using modulo operation to ensure the result will have no more than 6 digits. The %06d argument for sprintf will ensure that the result will have no less than 6 digits.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
char buf[7] = { 0 };
int r;
srand(time(NULL));
r = rand() % 1000000;
sprintf(buf, "%06d", r);
printf("foo-%s\n", buf);
return 0;
}

Your problem occurs when you attempt to call concat with the int value r as the second argument. Notice your definition of concat:
char* concat(char *s1, char *s2);
The second argument is char *s2. In your program you attempt to call it with:
int r = rand();
printf(concat("foo-", r));
r is an integer. Try this to correct the problem:
int main ()
{
srand(time(NULL));
int r = rand();
char str[] = "bar";
printf(concat("foo-", str));
return 0;
}

Related

sscanf get string until second symbol (include one)

How to get string until second symbol through sscanf?
for example:
char *str = "struct1.struct2.struct3.int";
char buf[256] = {0};
sscanf(str, "", buf); //have any format string could get string until second dot?
sscanf get string until second symbol (include one)
How to get string until second symbol through sscanf?
Not generally possible with a single use of sscanf().
Certainly, without a lot of work, a more involved use of sscanf() will work for many input strings, yet fail for select ones1. sscanf() is not the best fit here for this task.
strchr(), strcspn() better suited.
#include <string.h>
#include<stdlib.h>
// Return offset to 2nd needle occurrence
// or end of string, if not found.
size_t foo(const char *haystack, const char *needle) {
size_t offset = strcspn(haystack, needle);
if (haystack[offset]) {
offset++;
offset += strcspn(haystack + offset, needle);
}
return offset;
}
#include <stdio.h>
int main() {
const char *haystack = "struct1.struct2.struct3.int";
printf("<%.*s>\n", (int) foo(haystack, "."), haystack);
}
Output
<struct1.struct2>
1 Consider: "struct1.struct2", "struct1..", "..struct2", ".struct2.", "..", ".", "".
You can use a * to tell scanf to ignore an element:
const char *str = "struct1.struct2.struct3.int";
int main() {
char buf[256];
int i = sscanf(str, "%*[^.].%[^.]", buf);
printf("%d >%s<\n", i, buf);
return 0;
}
This outputs as expected:
1 >struct2<
because exactly 1 element was assigned even if another one was parsed.

parse integer without appending char in C

I want to parse an integer but my following code also accepts Strings like "3b" which start as a number but have appended chars. How do I reject such Strings?
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int n;
if(argc==2 && sscanf(argv[1], "%d", &n)==1 && n>0){
f(n);
return 0;
}
else{
exit(EXIT_FAILURE);
}
}
For your problem, you can use strtol() function from the #include <stdlib.h> library.
How to use strtol(Sample code from tutorial points)
#include <stdio.h>
#include <stdlib.h>
int main(){
char str[30] = "2030300 This is test";
char *ptr;
long ret;
ret = strtol(str, &ptr, 10);
printf("The number(unsigned long integer) is %ld\n", ret);
printf("String part is |%s|", ptr);
return(0);
}
Inside the strtol, it scans str, stores the words in a pointer, then the base of the number being converted. If the base is between 2 and 36, it is used as the radix of the number. But I recommend putting zero where the 10 is so it will automatically pick the right number. The rest is stored in ret.
The ctype.h library provides you the function isdigit(char) function that returns whether the char provided as argument is a digit or not.
You could iterate over argv[1] and check it this way.

What's wrong with this sscanf() format string?

I'm trying to parse a simple string: a character from the set "rgbcmyw" followed by a character form the set "slh" then an integer.
risk:9008:~$ cat test-scanf.c
#include <stdio.h>
int main(int argc, char ** argv) {
char c,m;
int s;
printf("Scanned %d elements.\n", sscanf(argv[1], "%[rgbcmyw]%[slh]%d", &c, &m, &s));
printf("Scanned:\n\tc = %c (%d)\n\tm = %c (%d)\n\ts = %d\n",c,c,m,m,s);
return 0;
}
risk:9012:~$ gcc test-scanf.c && ./a.out rs40
Scanned 3 elements.
Scanned:
c = (0)
m = s (115)
s = 40
risk:9013:~$
Why is zero being assigned to 'c'?
EDIT: The solution
One needs space for the character being scanned plus a nul termination:
#include <stdio.h>
int main(int argc, char ** argv) {
char c[2],m[2]; /* Need space for the character *and* the 'nul' termination. */
int s;
printf("Scanned %d elements.\n", sscanf(argv[1], "%[rgbcmyw]%[slh]%d", c, m, &s));
printf("Scanned:\n\tc = %s\n\tm = %s\n\ts = %d\n",c,m,s);
return 0;
}
You are using a string conversion specifier and a char pointer. %[foo] expects a pointer to char (and there must be enough room for all the characters in the string, plus a terminating null byte), not simply a pointer to a char.
Your code is passing the wrong type of parameters to sscanf(). The "%[] specifier expects a char * pointer.

C - Increment a number within a char

Is it possible to increment a number alone within a string?
So let's say I have:
char someString = "A0001";
Is there a way to increment the number '0001'? To make it A0002, A0003 etc?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
char *strinc(const char *str, int d, int min_width){
char wk[12];//12:max length of sizeof(int)=4
char *p;
int len, d_len, c;
c = len = strlen(str);
while(isdigit(str[--c]));
++c;
d += strtol(&str[c], NULL, 10);
if(d<0) d = 0;
d_len = sprintf(wk, "%0*d", min_width, d);
p = malloc((c+d_len+1)*sizeof(char));
strncpy(p, str, c);
p[c]='\0';
return strcat(p, wk);
}
int main(void){
char *someString = "A0001";
char *label_x2, *label_x3;
label_x2 = strinc(someString, +1, 4);
printf("%s\n", label_x2);//A0002
label_x3 = strinc(label_x2, +1, 4);
printf("%s\n", label_x3);//A0003
free(label_x2);
label_x2 = strinc("A0008", +5, 4);
printf("%s\n", label_x2);//A0013
free(label_x3);
label_x3 = strinc(label_x2, -8, 4);
printf("%s\n", label_x3);//A0005
free(label_x2);
free(label_x3);
return 0;
}
no u cannot do it because it is a constant
The simple answer is that there is no "easy" way to do what you're asking. You would have to parse the string, extract the numerical portion and parse into a number. Increment the number and then print that number back into your string.
You could try the following simple example to base something on...
EDIT: Just read BLUEPIXY's answer... he presents a nice function that will do it for you, return you a new string, which doesn't have the width restriction of my simple answer...
There are some points worth noting...
Use char someString[] = "A0001"; and not char *someString = "A0001";. The reason is that the former allocates memory on the stack for the string, the latter is a pointer to a string in memory. The memory location decided upon by the compiler in the latter case and is not always guaranteed to be writable.
Crappy #define for snprintf on Windows... not sure that's a good thing. The point is really use a safe buffer writing function that won't overflow the bounds of your array.
The snprintf format string "%0*u" Formats an unsigned integer with a minimum width specified by the argument to the left of the actual integer and the zero tells it to left pad with zeros if necessary.
If your number increases to a width greater than, in this case, 4 digits, the buffer won't overflow, but your answers will look wrong (I haven't put in any logic to increment the buffer size)
I am assuming the the format of the string is always a set of non-numerical-digits, followed by a set of numerical digits and then a null terminator.
Now the code...
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#ifdef WIN32
#define snprintf sprintf_s
#endif
int main(int argc, char* argv[])
{
/* Assume that the string format is letters followed by numbers */
/* Note use someString[] and NOT someString* */
char someString[] = "A0001";
char *start = someString;
char *end = start + strlen(someString); /* End points to the NULL terminator */
char *endOfParse;
char c;
unsigned long num;
ptrdiff_t numDigits;
/* Find first numeric value (start will point to first numeric
* value or NULL if none found */
while( true )
{
c = *start;
if( c == '\0' || isdigit(c) )
break;
++start;
}
if( c == '\0' )
{
printf("Error: didn't find any numerical characters\n");
exit(EXIT_FAILURE);
}
/* Parse the number pointed to by "start" */
num = strtoul(start, &endOfParse, 0);
if(endOfParse < end )
{
printf("Error: Failed to parse the numerical portion of the string\n");
exit(EXIT_FAILURE);
}
/* Figure out how many digits we parsed, so that we can be sure
* not to overflow the buffer when writing in the new number */
numDigits = end - start;
num = num + 1;
snprintf(start, numDigits+1, "%0*u", numDigits, num); /* numDigits+1 for buffer size to include the null terminator */
printf("Result is %s\n", someString);
return EXIT_SUCCESS;
}
You can't do it simply because its not as simple to machine as it looks to you. There are a lot of things you need to understand about what you are trying to do first. For example, What part of string are you taking as a number which is to be incremented?
Last digit only?
A number which will be followed by SINGLE alphabet?
A number which may be followed by any number of alphabets?
LAST number in a string, for example A33B43 would mean to increment 33 or 43?
When you have answers to all such questions, you can implement them in a function. One of the many possible approaches thereafter can be to make a new substring which will represent the number to be incremented(this substring is to be taken out from your someString). Then use atoi() to convert that string into number, increment the number and replace this incremented number as a string in someString.(someString needs to be String or char * btw).

Is there any function available for printing some characters instead of whole strings?

see
char str[] = "hello world";
printf("%s",str);
printf statement prints the all character in string before reaching '\0'
so what if i want to print just 4 1st character of str on stdout?
You can just specify the field width in the printf format string:
#include <stdio.h>
int main(void)
{
const char *s = "Hello world !";
printf("%.4s\n", s);
return 0;
}
or, if you want to specify the field width at run-time:
#include <stdio.h>
int main(void)
{
const char *s = "Hello world !";
const int fw = 4;
printf("%.*s\n", fw, s);
return 0;
}
In either case the output will be:
Hell
You can use %c in your format string:
printf("%c", *s);
prints 'H'
To print an arbitrary char:
printf("%c", s[3]);
prints 'l'
For the first character, you can just use:
printf ("%c", *str); // or
printf ("%c", *(str+0)); // or
printf ("%c", str[0]);
For a different character, just reach out and grab it by using an offset. For the second l at offset 3:
printf ("%c", str[3]); // or
printf ("%c", *(str+3));
For a substring, you can use a combination of that method along with the maximum field width feature of printf:
printf ("%.2s", str+3); // prints "lo"
With all these solutions, you want to make sure you don't start on the wrong side of the null terminator. That wouldn't be a good thing :-)
If you want a generalised solution that will work for any string, and is relatively safe in terms of finding the starting point, you can use:
void outSubstr (FILE *fh, char *str, size_t start, size_t sz, int padOut) {
if (start >= strlen (str)) {
if (padOut)
fprintf (fh, "%*s", sz, "");
return;
}
if (padOut)
fprintf (fh, "%-*.*s", sz, sz, str + start);
else
fprintf (fh, "%-.*s", sz, str + start);
}
The parameters are as follows:
fh is the file handle to write to.
str is the start of the string.
start is the offset to start printing from.
sz is the maximum number of characters to print.
padOut is a flag indicating that sz is also the minimum size. Output will be padded with spaces on the right if there are not enough characters in the string to satisfy the size.
This will print up to 4 characters.
printf("%.4s", str);
there is also a "substr()" function
that return the substring from complete string.
example
printf("%s",substr(str,0,4));
it has syntax like this
substr(arrayName,charStartingPosition, lengthOfCharacters);
i hope this is easy to understand and no need to write more than 1 statement.
Really less painful for the system :
int main(void)
{
char c;
c = 'z';
write(1, &c, 1);
}
No need for heavy stdio here
Then you can ...
char *s = "Hello, World!";
write(1, s, numberOfChars);
Or if you really want to do it char by char:
void printnchars(char *s, int n)
{
int i;
i = 0;
while (i <= n)
{
write(1, s + i, 1);
i++;
}
}
numOfChars = 4;
printf("%.*s\n", numOfChars, "Hello, world!");
Where numOfChars is the quantity of characters that you want to print.

Resources