The concept is very similar to this Add zero-padding to a string but it's a question from c# NOT C.
While you can add a zero padding in printf like this printf("%4d", number)
How can I have a zero padding to a string? ex:
char *file_frame = "shots";
strcat(file_frame, "%3d", number); // It's my attempt to solve it. I know it's wrong
so that I would get shots000 from file_frame
You need to use sprintf
sprintf(file_frame, "%04d", 34);
The 0 indicates what you are padding with and the 4 shows the length of the integer number.
Also you should be using mutable array as below.
char *file_frame = "shots"; --> char file_frame[100] = "shots";
First you need some space to store the string. Then you "print" into this string:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char file_name[8 + 1]; // "shots###" is 8 characters, plus 1 for end-of-string marker '\0'
int number = 23;
sprintf(file_name, "shots%03d", number);
printf("\"%s\"\n", file_name);
return EXIT_SUCCESS;
}
You can combine literal parts with formatting parts in any *printf() function.
Well, this is the workaround I did: -
char output[9];
char buffer[9];
itoa(num, output, 2);
int i=0;
for (i=0; i<(8-strlen(output));i++) {
buffer[i]='0';
}
for(int j=0;j<strlen(output);j++){
buffer[i] = output[j];
i++;
}
Input:-
num = 10
Output: -
buffer = 00001010
Related
I have an array:
char arr[]="This is the string";
For instance, if I want to print only first 5 characters of that string, I have tried the following:
printf("%-5s",arr);
But it is printing whole string. Why?
You can use %.*s, it takes size of intended bytes to be printed and pointer to char as arguments when using with printf. For example,
// It prints This
printf("%.*s", 4, arr);
But it is printing whole string. Why?
You are using %-5s meaning the - left-justifies your text in that field.
En passant, the output cannot be achieved by using the accepted answer as simply as the code snippet, even if it may be seemed derisively.
int i;
char arr[]="This is the string";
for (i = 1; i < sizeof(arr); ++i) {
printf("%.*s\n", i, arr);
}
Output:
T
Th
Thi
This
This
This i
This is
This is
This is t
This is th
This is the
This is the
This is the s
This is the st
This is the str
This is the stri
This is the strin
This is the string
- is a printf formater for justification, not precision.
What you want is the . formater which is used for precision :
printf("%.5s", arr);
This will print the first 5 elements of arr.
If you want to learn more about printf formaters, take a look at this link.
for example substring extraction function (extracts substring to the buff)
char *strpart(char *str, char *buff, int start, int end)
{
int len = str != NULL ? strlen(str) : -1 ;
char *ptr = buff;
if (start > end || end > len - 1 || len == -1 || buff == NULL) return NULL;
for (int index = start; index <= end; index++)
{
*ptr++ = *(str + index);
}
*ptr = '\0';
return buff;
}
You can do it quite simply in a number of ways. With a loop, looping the number of times desired, picking off chars each time, you can walk a pointer down the string an temporary nul-terminate after the 5th character, or you can simply use strncpy to copy 5 chars to a buffer and print that. (that is probably the simplest), e.g.
#include <stdio.h>
#include <string.h>
int main (void)
{
char arr[]="This is the string",
buf[sizeof arr] = ""; /* note: nul-termination via initialization */
strncpy (buf, arr, 5);
printf ("'%s'\n", buf);
return 0;
}
Example Use/Output
$ ./bin/strncpy
'This '
Look things over and let me know if you have any questions.
I am converting string arguments into ints I am having an issue where the first argument is not copying and converting to a string while the second argument is working just fine. I am removing the first character of the string array and printing out the rest of the string as an int.
#include <stdio.h>
#include <string.h>
#include <math.h>
int main(int argc, char *argv[])
{
char numcpy1[sizeof(argv[1])-1];
char numcpy2[sizeof(argv[2])-1];
int i, len1, len2;
int result1=0;
int result2=0;
//Access first character for base
printf("%c \n", argv[2][0]);
printf("%c \n", argv[3][0]);
//Remove first character for number1 and number 2
if(strlen(argv[2]) > 0)
{
strcpy(numcpy1, &(argv[2][1]));
}
else
{
strcpy(numcpy1, argv[2]);
}
len1 = strlen(numcpy1);
if(strlen(argv[3]) > 0)
{
strcpy(numcpy2, &(argv[3][1]));
}
else
{
strcpy(numcpy2, argv[3]);
}
len2 = strlen(numcpy2);
//Turn remaining string characters into an int
for(i=0; i<len1; i++)
{
result1 = result1 * 10 + ( numcpy1[i] - '0' );
}
for(i=0; i<len2; i++)
{
result2 = result2 * 10 + ( numcpy2[i] - '0' );
}
printf("%d \n", result1);
printf("%d \n", result2);
return 0;
}
Output:
b
b
-4844
1010
What I want:
b
b
1000
1010
The sizeof operator does not give you the length of a string, as you seem to think it does. It tell you the size of the datatype. Since argv[2] is a char *, this evaluates to the size of this pointer, most likely 4 or 8 depending on the system.
If the string in question is longer than this value, you end up writing past the end of the array. This invokes undefined behavior, which in your case manifests as an unexpected result.
If you want the length of the string, use the strlen function instead. Also, you need to add one more byte. Strings in C are null terminated, so you need space for the null byte that marks the end of the string.
char numcpy1[strlen(argv[2])];
char numcpy2[strlen(argv[3])];
Also note that we don't need to add 1 to each of these since the first character in each string isn't copied.
You need to change
char numcpy1[sizeof(argv[1])-1];
to
char numcpy1[strlen(argv[1]) + 1];
Ditto for numcpy2
I think instead of copying the numbers you could work more easily with pointers. Thereby, you don't have to think about memory allocation and copying the values just for the sake of converting them into an integer value:
const char *numcpy1 = argv[2][0]=='\0' ? argv[2] : argv[2]+1;
...
I have a hex string in the form of "404C49474854" .
I am trying to extract the text string out of it with :
void textFromHexString(char *hex,char *result)
{
for(int k=1;k<strlen(hex);k+=2)
{
char temp[3]={0};
sprintf(temp,"%c%c",hex[k-1],hex[k]);
*result=char((int)strtol(temp, NULL, 16));
result++;
*result ='\0';
print(temp); //**** edit
}
}
I call it from inside another function, with :
void somefunction()
{
// I have p here, which prints "404C49474854"
char text[TEXT_MAX_SIZE]={0};
textFromHexString(p,text);
}
It works, but it works 80% of the time. in some cases it crashes, where :
-incoming hex pointer is : "404C49474854". for sure .
-where the pointer temp get a completely other values that are not even inside hex.
Is there something basically wrong with this method ?
EDIT:
Check where the line that prints inside the loop, it will print this in a very specific situation :
4Hello, world
How temp, that consist of numbers only, gets this string ? (the "Hello world", is just a string I print at the beginning of the program, also temp size is 3)
You can use sscanf() to directly read hexadecimal numbers of a given length, like so:
while(hex[0] && hex[1]) {
int value;
sscanf(hex, "%2x", &value);
printf("%c", value);
hex += 2;
}
printf("\n");
It seems as if most errors were found by the commenters, so here is code that works under the assumption that I guessed right what you want.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
// ALL CHECKS OMMITTED!
void textFromHexString(char *hex, char result[])
{
// work on copy
char *p = result;
// this has more steps than necessary for clarity
for (size_t k = 1; k < strlen(hex); k += 2) {
// normalize input
char first = tolower(hex[k - 1]);
char second = tolower(hex[k]);
// convert hexbyte to decimal number
int f1 = (isdigit(first)) ? first - '0' : (first - 'a') + 10;
int f2 = (isdigit(second)) ? second - '0' : (second - 'a') + 10;
// two byte number from LSB hex to decimal (e.g.: "ab" = 171)
int num = f1 * 16 + f2;
// needs to store min. 3 characters plus NUL
char temp[4] = { 0 };
// sprintf is a bit too much for it but simple
sprintf(temp, "%d", num);
// concatenate temp to the result-string
strcat(p, temp);
// For debugging, I guess, or further work?
printf("%s\n", temp);
}
}
#define TEXT_MAX_SIZE 64
int main()
{
// 0x404C49474854 = 70696391100500
char *p = "404C49474854";
// allocate some scratchspace on the stack
char text[TEXT_MAX_SIZE] = { 0 };
textFromHexString(p, text);
// the function textFromHexString() does it in chunks of two bytes,
// so the result is 647673717284 here
printf("Result: %s\n", text);
exit(EXIT_SUCCESS);
}
I want to convert a section of a char array to a double. For example I have:
char in_string[] = "4014.84954";
Say I want to convert the first 40 to a double with value 40.0. My code so far:
#include <stdio.h>
#include <stdlib.h>
int main(int arg) {
char in_string[] = "4014.84954";
int i = 0;
for(i = 0; i <= sizeof(in_string); i++) {
printf("%c\n", in_string[i]);
printf("%f\n", atof(&in_string[i]));
}
}
In each loop atof it converts the char array from the starting pointer I supply all the way to the end of the array. The output is:
4
4014.849540
0
14.849540
1
14.849540
4
4.849540
.
0.849540
8
84954.000000 etc...
How can I convert just a portion of a char array to a double? This must by modular because my real input_string is much more complicated, but I will ensure that the char is a number 0-9.
The following should work assuming:
I will ensure that the char is a number 0-9.
double toDouble(const char* s, int start, int stop) {
unsigned long long int m = 1;
double ret = 0;
for (int i = stop; i >= start; i--) {
ret += (s[i] - '0') * m;
m *= 10;
}
return ret;
}
For example for the string 23487 the function will do this calculations:
ret = 0
ret += 7 * 1
ret += 8 * 10
ret += 4 * 100
ret += 3 * 1000
ret += 2 * 10000
ret = 23487
You can copy the desired amount of the string you want to another char array, null terminate it, and then convert it to a double. EG, if you want 2 digits, copy the 2 digits you want into a char array of length 3, ensuring the 3rd character is the null terminator.
Or if you don't want to make another char array, you can back up the (n+1)th char of the char array, replace it with a null terminator (ie 0x00), call atof, and then replace the null terminator with the backed up value. This will make atof stop parsing where you placed your null terminator.
Just use sscanf. Use the format "ld" and check for return value is one.
What about that, insert NULL at the right position and then revert it back to the original letter? This means you will manipulate the char array but you will revert it back to the original at the end.
You can create a function that will make the work in a temporary string (on the stack) and return the resulting double:
double atofn (char *src, int n) {
char tmp[50]; // big enough to fit any double
strncpy (tmp, src, n);
tmp[n] = 0;
return atof(tmp);
}
How much simpler could it get than sscanf?
#include <assert.h>
#include <stdio.h>
int main(void) {
double foo;
assert(sscanf("4014.84954", "%02lf", &foo) == 1);
printf("Processed the first two bytes of input and got: %lf\n", foo);
assert(sscanf("4014.84954" + 2, "%05lf", &foo) == 1);
printf("Processed the next five bytes of input and got: %lf\n", foo);
assert(sscanf("4014.84954" + 7, "%lf", &foo) == 1);
printf("Processed the rest of the input and got: %lf\n", foo);
return 0;
}
I am looking for a (relatively) simple way to parse a random string and extract all of the integers from it and put them into an Array - this differs from some of the other questions which are similar because my strings have no standard format.
Example:
pt112parah salin10n m5:isstupid::42$%&%^*%7first3
I would need to eventually get an array with these contents:
112 10 5 42 7 3
And I would like a method more efficient then going character by character through a string.
Thanks for your help
A quick solution. I'm assuming that there are no numbers that exceed the range of long, and that there are no minus signs to worry about. If those are problems, then you need to do a lot more work analyzing the results of strtol() and you need to detect '-' followed by a digit.
The code does loop over all characters; I don't think you can avoid that. But it does use strtol() to process each sequence of digits (once the first digit is found), and resumes where strtol() left off (and strtol() is kind enough to tell us exactly where it stopped its conversion).
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
int main(void)
{
const char data[] = "pt112parah salin10n m5:isstupid::42$%&%^*%7first3";
long results[100];
int nresult = 0;
const char *s = data;
char c;
while ((c = *s++) != '\0')
{
if (isdigit(c))
{
char *end;
results[nresult++] = strtol(s-1, &end, 10);
s = end;
}
}
for (int i = 0; i < nresult; i++)
printf("%d: %ld\n", i, results[i]);
return 0;
}
Output:
0: 112
1: 10
2: 5
3: 42
4: 7
5: 3
More efficient than going through character by character?
Not possible, because you must look at every character to know that it is not an integer.
Now, given that you have to go though the string character by character, I would recommend simply casting each character as an int and checking that:
//string tmp = ""; declared outside of loop.
//pseudocode for inner loop:
int intVal = (int)c;
if(intVal >=48 && intVal <= 57){ //0-9 are 48-57 when char casted to int.
tmp += c;
}
else if(tmp.length > 0){
array[?] = (int)tmp; // ? is where to add the int to the array.
tmp = "";
}
array will contain your solution.
Just because I've been writing Python all day and I want a break. Declaring an array will be tricky. Either you have to run it twice to work out how many numbers you have (and then allocate the array) or just use the numbers one by one as in this example.
NB the ASCII characters for '0' to '9' are 48 to 57 (i.e. consecutive).
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
int main(int argc, char **argv)
{
char *input = "pt112par0ah salin10n m5:isstupid::42$%&%^*%7first3";
int length = strlen(input);
int value = 0;
int i;
bool gotnumber = false;
for (i = 0; i < length; i++)
{
if (input[i] >= '0' && input[i] <= '9')
{
gotnumber = true;
value = value * 10; // shift up a column
value += input[i] - '0'; // casting the char to an int
}
else if (gotnumber) // we hit this the first time we encounter a non-number after we've had numbers
{
printf("Value: %d \n", value);
value = 0;
gotnumber = false;
}
}
return 0;
}
EDIT: the previous verison didn't deal with 0
Another solution is to use the strtok function
/* strtok example */
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] = "pt112parah salin10n m5:isstupid::42$%&%^*%7first3";
char * pch;
printf ("Splitting string \"%s\" into tokens:\n",str);
pch = strtok (str," abcdefghijklmnopqrstuvwxyz:$%&^*");
while (pch != NULL)
{
printf ("%s\n",pch);
pch = strtok (NULL, " abcdefghijklmnopqrstuvwxyz:$%&^*");
}
return 0;
}
Gives:
112
10
5
42
7
3
Perhaps not the best solution for this task, since you need to specify all characters that will be treated as a token. But it is an alternative to the other solutions.
And if you don't mind using C++ instead of C (usually there isn't a good reason why not), then you can reduce your solution to just two lines of code (using AXE parser generator):
vector<int> numbers;
auto number_rule = *(*(axe::r_any() - axe::r_num())
& *axe::r_num() >> axe::e_push_back(numbers));
now test it:
std::string str = "pt112parah salin10n m5:isstupid::42$%&%^*%7first3";
number_rule(str.begin(), str.end());
std::for_each(numbers.begin(), numbers.end(), [](int i) { std::cout << "\ni=" << i; });
and sure enough, you got your numbers back.
And as a bonus, you don't need to change anything when parsing unicode wide strings:
std::wstring str = L"pt112parah salin10n m5:isstupid::42$%&%^*%7first3";
number_rule(str.begin(), str.end());
std::for_each(numbers.begin(), numbers.end(), [](int i) { std::cout << "\ni=" << i; });
and sure enough, you got the same numbers back.
#include <stdio.h>
#include <string.h>
#include <math.h>
int main(void)
{
char *input = "pt112par0ah salin10n m5:isstupid::42$%&%^*%7first3";
char *pos = input;
int integers[strlen(input) / 2]; // The maximum possible number of integers is half the length of the string, due to the smallest number of digits possible per integer being 1 and the smallest number of characters between two different integers also being 1
unsigned int numInts= 0;
while ((pos = strpbrk(pos, "0123456789")) != NULL) // strpbrk() prototype in string.h
{
sscanf(pos, "%u", &(integers[numInts]));
if (integers[numInts] == 0)
pos++;
else
pos += (int) log10(integers[numInts]) + 1; // requires math.h
numInts++;
}
for (int i = 0; i < numInts; i++)
printf("%d ", integers[i]);
return 0;
}
Finding the integers is accomplished via repeated calls to strpbrk() on the offset pointer, with the pointer being offset again by an amount equaling the number of digits in the integer, calculated by finding the base-10 logarithm of the integer and adding 1 (with a special case for when the integer is 0). No need to use abs() on the integer when calculating the logarithm, as you stated the integers will be non-negative. If you wanted to be more space-efficient, you could use unsigned char integers[] rather than int integers[], as you stated the integers will all be <256, but that isn't a necessity.