I'm working on prefixing of a string for example : com should give me c co com.
I know to print a character in this was printf("%.5s",string) to print the first five values. I want to do this in a loop instead of 5 how can I replace it with i which is a incrementing value,something like this printf("%.is",string). how can I obtain this?
In printf format specifiers, all field widths (before the dot) and precisions (after the dot) can be given as asterisk *. For each asterisk, there must be one additional int argument before the printed object.
So, for your problem:
printf("%.*s", i, string);
Note that the additional parameter must be an int, so if you have another integer type, you should cast it:
size_t len = strlen(len);
if (len > 2) printf("%.*s", (int) (len - 2), string);
This is the simplest way of achieving what you want.
printf("%.*s\n", i, string);
If you want to generate the format string, you can do it too
char format[100]; /* the size should be estimated by you */
snprintf(format, sizeof(format), "%%.%ds", i);
printf(format, string)
check the snprintf() return value to ensure that the string was not truncated, if you choos a reasonable size for the format string it will be unlikely, but you should check anyway.
Above, the format specifier means
A literal "%"
Then a "."
Then the integer "%d"
Then the letter "s"
so the resulting string will be the format string you need to pass to printf().
Try this:
char s[] = "com";
for(size_t i = 1; i <= strlen(s); i++)
{
for(int j = 0; j < i; j++)
printf("%c", s[j]);
printf(" ");
}
Related
I'm trying to write a program that does the following:
Enter a word: supercalifragilisticoespialidoso
The word's length is: 32.
Enter a smaller number than the length: 23
The word cut on letter 23 is: supercalifragilisticoes.
For that I'm doing:
#include <stdio.h>
#include<string.h>
#define DIM 99
int main() {
char name[DIM], name2[DIM];
int length, length2;
printf("Enter a word: ");
scanf("%s", name);
length = strlen(name);
printf("The word's length is: %d\n", length);
printf("Enter a smaller number than the length: ");
scanf("%d", &length2);
name2 = name[length2];
printf("The word cut on the letter %d is: %c", length2, name2);
return 0;
}
But I get
main.c:16:11: error: assignment to expression with array type
The problem is in the line name2 = name[length2], that's the way I found to create the new smaller word, but it's not right.
Could someone please help?
The mistake is in the line
name2 = name[length2];
You're trying to assign a character (the one of index length2 inside name) to an array (name2).
What you actually want to do is this:
strncpy(name2, name, length2);
name2[length2] = '\0';
This copies the first length2 bytes of name into name2 and adds a terminating null character for safety (strncpy doesn't do it if all of the bytes are written).
If you don't intend to use name again, you could as well remove name2 altogether and add a null character to name:
name[length2] = '\0';
You're also printing a string with a %c format specifier on the last printf call. You should use %s instead.
Other answers have suggested how you might make a copy of the initial substring of your input or how to modify the input string in place. Those are perfectly good approaches, and both have plenty of uses in real-world programs.
However, if all your program needs to do is print the wanted substring then there is no need to do any string manipulation at all. printf can do the job by itself. Given the variables as you declared them and this code ...
scanf("%s", name);
length = strlen(name);
printf("The word's length is: %d\n", length);
printf("Enter a smaller number than the length: ");
scanf("%d", &length2);
... you can use a printf format to print name into a bounded-length field whose length is given by another printf argument:
printf("%.*s\n", length2, name);
That also adds a newline after, which is usually what one wants, but you can leave that off if you prefer.
The .* in the formatting directive indicates that a "precision" is being specified for the field via a printf argument. Other variations can express a fixed precision directly in the format. The significance of a precision depends somewhat on the directive type, but for s directives it is the maximum number of characters to be printed from the corresponding string argument.
There are two main errors in your code, and a couple of other minor points.
First, you can't directly assign arrays (be they character strings or any other array type) in C; for nul-terminated char arrays (strings), you can copy one to another using the strcpy function, or copy part of one to another using strncpy (which is what you want in your case).
Second, you can't print a string using the %c format specifier – you need %s for those.
And, a less serious issue (but one to avoid, if you want to be a good programmer) is that functions that work with string lengths (like strlen and strncpy) generally use size_t types, rather than int; and these require using the %zu format specifier, in place of %d.
Here's a version of your code that does what you want:
#include <stdio.h>
#include<string.h>
#define DIM 99
int main()
{
char name[DIM], name2[DIM] = { 0 }; // Fill with zeros to start, so we will have a nul terminator
size_t length, length2; // Strictly, use "size_t" for "strlen" and "strncpy"
printf("Enter a word: ");
scanf("%s", name);
length = strlen(name);
printf("The word's length is: %zu\n", length); // Use "%zu" for the "size_t" type
printf("Enter a smaller number than the length: ");
scanf("%zu", &length2); //Again, "%zu" for "size_t"
strncpy(name2, name, length2); // Use this function to copy a substring!
printf("The word cut on the letter %zu is: %s", length2, name2);// Note that you need "%s" to print a string
return 0;
}
There are some other 'safety measures' that you can add to your code, to prevent buffer overruns and other faults. One would be to limit the initial string input to at most DIM - 1 characters; this would be trivial if you had a hard-coded value of 99 in place of DIM, because then you could use a call like the following:
scanf("%98s", name); // Read at most 98 characters (leaving space for the nul-terminator)
However, the macro DIM cannot be used inside the quoted format string. Instead, you can write its value (minus 1) into a separate string and use that as the format argument to scanf; so, we replace our initial scanf call, like so:
// scanf("%s", name); // This has the potential to overrun the "name" array!
char fmt[8];
sprintf(fmt, "%%%ds", DIM - 1); // Write "%98s" into the "fmt" string ...
scanf(fmt, name); // ...and use that for the "scanf" format
(Note that some compilers will warn about not using a string literal for the format argument, and some programmers may not 'approve' of doing so; however, it is perfectly legal C and, IMHO, a valid use of the scanf function.)
The assignment:
name2 = name[length2];
does not have the semantics you appear to have assumed. Rather name2 is an array while name[length2] is a a single character at the index length2 of the array name.
In any event arrays are not first-class data types in C and you cannot assign one array to another (as it appears you were perhaps intending) let alone assigning a char for an array.
Here you might explicitly strncpy() to copy the sub-string, but in this case that is perhaps unnecessary. You can simply remove the name2 array and:
printf( "The word cut on the letter %d is: ", length2 ) ;
for( int i = 0; i < length && i < length2; i++ )
{
putchar( name[i] ) ;
}
If you truly need to store the sub-string rather then simply outputting it then:
int i = 0 ;
for( i = 0; i < length && i < length2; i++ )
{
name2[i] = name[i] ;
}
name2[i] = '\0' ;
Both have the advantage of behaving deterministically if length2 were less than zero or greater than length which you fail to check.
Using strncpy():
int len = (length2 < 0 || length2 > length) ?
length :
length2 ;
strncpy( name2, name, len ) ;
name2[len] = '\0' ;
Of course all those length checks are largely defeated by the lack of safety in acquiring name in the manner you have in the first instance. Consider using fgets() instead, or even getchar() in a loop.
I have an int value in the input and I want to save it to a buffer/array as a hexadecimal representation of ASCII.
I know how to print it in hex form but how can I save it like this to the buffer?
Here's the code I wrote:
int a = 98765;
char buffer[20];
m = sprintf(buffer, "%d", a);
printf("ASCII value in hex: ");
for(int i=0; buffer[i]!='\0'; i++)
{
printf("%02X", buffer[i]);
}
for eg if a=123 I want to get 313233
The first sprintf gave you an array of char, where each one is in the range 0x30 to 0x39. You want those to be expanded to the two characters '3' and '0', '3' and '1', etc.
You're expanding each char in the source to two chars in the output, which means you can't use the same destination buffer as source buffer -- you'd overwrite values in the source buffer before you processed them. You probably want to do the first sprintf into a separate array of char if you need the result in buffer. In your loop, change the printf to a sprintf to an index in buffer, incrementing your index by two each loop. (By two because that way you'll be overwriting the first iteration's string terminator with the second iteration's sprintf output, which will include a new string terminator. The sprintf in the last iteration of the loop will terminate the string for you.)
You didn't mention the longest input you're supposed to handle, or why you chose the array lengths you did. There's a danger of buffer overruns here if you accept inputs that are too long for your buffers (and don't forget to account for space for the null termination after the last character.)
You have already used sprintf to represent decimal values as a string; you can do the same for hexadecimal formatting.
Use the return value of sprintf() (which is the number of characters 'printed') to advance an index into the buffer as the destination for the next hex-digit pair, then iterate each character in the decimal buffer.
Note that, you can use the return value (m) from the first sprintf() for the iteration rather then testing for nul.
char hexbuffer[64];
int index = 0 ;
for(int i = 0; i < m; i++)
{
index += sprintf( &hexbuffer[index], "%02X", buffer[i] ) ;
}
Of course if the input includes only decimal digits (i.e. the user does not enter a negative value causing a - at buffer[0], you could simply insert a 3 ahead of each decimal digit, thus:
char hexbuffer[64];
for(int i = 0; i < m; i++)
{
bexbuffer[i * 2] = '3' ;
hexbuffer[i * 2 + 1] = buffer[i]
}
If only decimal digits were intended, you should change the type of a to unsigned and use the %u format specifier for the decimal input.
I want to copy all the characters in a char[] to another char[]. However, suppose there are is a '\0' then I want to treat that as a normal character--a literal if you will.
Therefore, when I printout the char[] with the format specifier %s, it should not stop in the middle.
e.g.
// chars copied to array x
char x[] = {'h','e','\0','l','l','o','\0'}
printf("%s\n",x); // prints 'he\0llo'
Is there a way to do this?
Use memcpy if you know how many characters you need to copy. If x is a real array as in your example, sizeof(x) will give you that amount, but if you pass x as a parameter to a function, sizeof will not work inside that function (it will just show the size of the pointer), so the basic rule is that your strings either should be NUL-terminated, or you should keep their size in a separate variable.
For printing, you can either print in the for loop as #alk suggests, or use fwrite to write any buffer (possibly with NULs) to stdout:
fwrite(x, sizeof(x), 1, stdout); /* sizeof will work only for a real array */
Wrong use of "%s". There is not a way to use printf("%s" to print an array with data after the first null character or '\0'.
char x[] = {'h','e','\0','l','l','o','\0'}
printf("%s\n",x); // This only prints "he"
printf("%s",... is for printing strings. x is a string only up to and including the first '\0'.
To "copy all the characters in a char[] to another char[].", use memcpy().
char x[] = {'h','e','\0','l','l','o','\0'}
char y[sizeof x];
memcpy(y, x, sizeof x);
Code could use "%c" to print everything, but what gets printed with '\0' varies amongst systems.
size_t i;
for (i=0; i< sizeof x; i++)
printf("%c", x[i]);
You need to print the array element wise, translating non-printable characters to whatever you want to see instead.
To print out he\0llo\0 do:
char x[] = {'h','e','\0','l','l','o','\0'};
for (size_t i = 0; i < sizeof(x); ++i)
{
if ('\0' == x[i])
{
printf("%s", "\\0");
}
else
{
printf("%c", x[i]);
}
}
I have read about %02x format specifiers but when it comes to an argument of type char array, I am unable to understand the output of the following piece of code:
int main() {
// your code goes here
char str[6] = "abcde";
char t[3];
snprintf(t,3,"%02x",str);
printf("\t%s",t);
return 0;
}
Output:
bf
How str is being parsed under this format specifier, is a point of concern. What I feel, the output should have been "ab" (without quotes).
The point to make here is that if you are printing anything using %02x then you should be using it for each byte. It is common when printing a hash digest to declare a field of size twice the digest size (+1 for \0 if a string) and then populate it with repetitive sprintf() calls.
So one needs to loop through the bytes.
Have a look at the CPlusPlus entry on printf.
I think the format specifier you are looking for is %2.2s, which limits the minimum and maximum number of characters printed to 2, and it will print a string, rather than the value of your pointer.
main(){
printf("%2.2s","abcde");
return 0;
}
This will print "ab" (without the quotes). The same format rules apply to the entire printf family, including snprintf.
%02x is a format specifier that tells the parser that your value is a number, you want it to be printed in base 16, you want there to be at least 2 characters printed, and that any padding it applies should be full of zeroes, rather than spaces. You need to use some version of %s for printing strings.
You should read your source carefully. They might use something like this:
int main() {
char str[6] = "abcde";
char t[2*6] = { 0 };
int i;
for (i = 0; i <= 5; ++i)
{
snprintf(t+2*i, sizeof(t)-2*(i), "%02x", str[i]);
}
printf("\t%s",t);
return 0;
}
The %02x is used to convert one character to a hexadecimal string. Therefore you need to access individual charaters of str. You can build a line as my code shows or you can output each converted string as your fragment shows. But then it doesn't make sense to use the temporary variable t.
Edit: Fixed code.
I'm trying to parse xxxxxx(xxxxx) format string using sscanf as following:
sscanf(command, "%s(%s)", part1, part2)
but it seems like sscanf does not support this format and as a result, part1 actually contains the whole string.
anyone has experience with this please share...
Thank you
Converting your code into a program:
#include <stdio.h>
int main(void)
{
char part1[32];
char part2[32];
char command[32] = "xxxxx(yyyy)";
int n;
if ((n = sscanf(command, "%s(%s)", part1, part2)) != 2)
printf("Problem! n = %d\n", n);
else
printf("Part1 = <<%s>>; Part2 = <<%s>>\n", part1, part2);
return 0;
}
When run, it produces 'Problem! n = 1'.
This is because the first %s conversion specifier skips leading white space and then scans for 'non white-space' characters up to the next white space character (or, in this case, end of string).
You would need to use (negated) character classes or scansets to get the result you want:
#include <stdio.h>
int main(void)
{
char part1[32];
char part2[32];
char command[32] = "xxxxx(yyyy)";
int n;
if ((n = sscanf(command, "%31[^(](%31[^)])", part1, part2)) != 2)
printf("Problem! n = %d\n", n);
else
printf("Part1 = <<%s>>; Part2 = <<%s>>\n", part1, part2);
return 0;
}
This produces:
Part1 = <<xxxxx>>; Part2 = <<yyyy>>
Note the 31's in the format; they prevent overflows.
I'm wondering how does %31 works. Does it work as %s and prevent overflow or does it just prevent overflow?
With the given data, these two lines are equivalent and both safe enough:
if ((n = sscanf(command, "%31[^(](%31[^)])", part1, part2)) != 2)
if ((n = sscanf(command, "%[^(](%[^)])", part1, part2)) != 2)
The %[...] notation is a conversion specification; so is %31[...].
The C standard says:
Each conversion specification is introduced by the character %.
After the %, the following appear in sequence:
An optional assignment-suppressing character *.
An optional decimal integer greater than zero that specifies the maximum field width
(in characters).
An optional length modifier that specifies the size of the receiving object.
A conversion specifier character that specifies the type of conversion to be applied.
The 31 is an example of the (optional) maximum field width. The [...] part is a scanset, which could perhaps be regarded as a special case of the s conversion specifier. The %s conversion specifier is approximately equivalent to %[^ \t\n].
The 31 is one less than the length of the string; the null at the end is not counted in that length. Since part1 and part2 are each an array of 32 char, the %31[^(] or %31[^)] conversion specifiers prevent buffer overflows. If the first string of characters was more than 31 characters before the (, you'd get a return value of 1 because of a mismatch on the literal open parenthesis. Similarly, the second string would be limited to 31 characters, but you'd not easily be able to tell whether the ) was in the correct place or not.
If you know exactly how long are the parts of your "command", then the simplest option is:
sscanf(command, "%6s(%5s)", part1, part2);
This assumes that 'part1' is always 6 characters long and 'part2' is always 5 characters long (as in your code sample).
Try this instead:
#include <stdio.h>
int main(void)
{
char str1[20];
char str2[20];
sscanf("Hello(World!)", "%[^(](%[^)])", str1, str2);
printf("str1=\"%s\", str2=\"%s\"\n", str1, str2);
return 0;
}
Output (ideone):
str1="Hello", str2="World!"