inserting comma in a large int number - c

i am trying to insert a comma in a large integer number eg, 870120000 and present it as: 870,120 and the last three digits are discarded. The format will allways be the same, ie., xxxxxxxxx number where i am only interested in the first 6 digits.
What i have been doing so fare is using snprintf:
#include <stdio.h>
#include <string.h>
int main()
{
char buffer[5];
unsigned int lNum= 870120000;
int cx;
memset(buffer,0,sizeof(buffer));
cx = snprintf(buffer, 4, "%d,", lNum);
buffer[3] = ',';
printf("%s\n",buffer);
cx = snprintf(buffer+4, 4, "321"); // Note 1 ???
printf("%s\n", buffer);
return 0;
}
My problem is that i am stuck at (comment // Note 1), how do I add the last next three digits in to buffer ?
in addition I would like to know if this approch is ideal or is there any better(easier) way to do this?

You can do that in two steps. First convert the lNum into a string, then cut the needed parts out of this string. Something like that.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char tmp[256], out[256];
unsigned int lNum= 870120000;
sprintf(tmp, "%u", lNum);
sprintf(out, "%3.3s,%3.3s", tmp, tmp+3);
printf("%s\n", out); // prints 870,120
return 0;
}
See http://ideone.com/bnQNou
Or you can convert it into a float and change the locale to have "," as delimiter:
#include <stdio.h>
#include <locale.h>
int main()
{
unsigned int lNum = 870120000;
setlocale(LC_NUMERIC, "de_DE");
printf("%3.3f\n", (float)(870120000 / 1000000)); // prints 870,120
return 0;
}

First of all to hold 870,120 you have to define a 8 chars buffer.
So you can use %f format specifier to do what you the job, e.g.:
#include <stdio.h>
#include <string.h>
int main()
{
char buffer[8] = {0};
unsigned int lNum= 870120000;
snprintf(buffer, sizeof(buffer), "%3.3f", (float)(lNum)/(1000000));
char *temp = strstr(buffer, ".");
if (temp != NULL)
{
*temp = ',';
}
printf("%s\n",buffer);
return 0;
}
or another example using double snprintf and a given number of integer part digits and decimal part digits.
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#define INT_DIGIT 3
#define DEC_DIGIT 3
int main()
{
char temp_buffer[128];
char buffer[INT_DIGIT+DEC_DIGIT+2] = {0};
unsigned int lNum= 87012000;
snprintf(temp_buffer, sizeof(temp_buffer), "%u",lNum);
snprintf(buffer, sizeof(buffer), "%.*s,%.*s", INT_DIGIT, temp_buffer, DEC_DIGIT, &temp_buffer[INT_DIGIT]);
printf("%s\n",buffer);
return 0;
}

Related

How do I convert a string to uppercase using the standard library?

I am trying to use a for loop with ASCII table to make every character in the string uppercase one by one by subtracting the letter number with 32. but I cant use the int i in the char str and str2. how can I do this?
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#define STRLEN 200
void string_lower() {
}
void string_upper(char str) {
char str2;
int length = strlen(str);
for (int i = 0; i < length; i++) {
str2[i] = str[i - 32];
}
}
int main() {
char word[STRLEN] = { 0 };
char word1 = 97;
printf("Write a word");
fgets(word, STRLEN, stdin);
string_upper(word);
return 0;
}
You can use toupper() to uppercase one character at a time. This will work for single byte character sets such as ASCII, but not for the UTF-8 encoding in general use today for non English scripts.
Here is a modified version:
#include <ctype.h>
#include <stdio.h>
#define STRLEN 200
char *string_upper(char *str) {
for (size_t i = 0; str[i] != '\0'; i++) {
str[i] = toupper((unsigned char)str[i]);
}
return str;
}
int main() {
char word[STRLEN];
printf("Enter a word: ");
if (fgets(word, STRLEN, stdin)) {
printf("%s", string_upper(word);
}
return 0;
}
The argument must be cast as (unsigned char)str[i] because str[i] has type char and tolower() like all functions and macros from <ctype.h> is only defined for values of the type unsigned char and the special negative value EOF. As char may be signed on some platforms, passing it directly to tolower() would have undefined behavior for negative values such as 'é' and 'ÿ'.
If you just want to make a function to convert your String to upper, maybe you can refer to the below example.
#include <stdio.h>
#include <ctype.h>
#define STRLEN 200
void string2upper(char *str){
int cursor=0;
while(*(str+cursor)!='\0'){
*(str+cursor) = toupper(*(str+cursor));
cursor++;
}
}
void main() {
char String1[STRLEN];
printf("Write a word:\n");
fgets(String1, STRLEN, stdin);
printf("Before : %s\n", String1);
string2upper(String1);
printf("After : %s\n", String1);
}
For the toupper() function, I think you can refer to this Link.
That has a detailed explanation and simple example to understand.
I think to know the function detail is better than only using~

segfault reading wide-oriented stream with locale settings

I have problem in program with locale and reading from stdin with fgetws function.
#include <stdio.h>
#include <locale.h>
#include <wchar.h>
static const int N = 2;
int main(void) {
setlocale(LC_ALL, "");
wchar_t data[N];
fgetws(data, N, stdin);
printf("%ls\n", data);
/* fclose(stdin); */
return 0;
}
When input is long enough (5 or more chars) I get segfault if I don't close stdin before return. Why is that? What is wrong with this program?
Suspect fgetws(data, 2, stdin) is broken.
fgetws(), using such a small buffer should, at most, read 1 wchar_t from stdin and append a termanting (wchar_t) '\0'.
As usual, when code fails mysteriously, best to check return from the functions to see if they are as expected.
#include <stdio.h>
#include <locale.h>
#include <wchar.h>
#include <assert.h>
#include <stdio.h>
#include <locale.h>
#include <wchar.h>
static const int N = 2;
int main(void) {
char *p = setlocale(LC_ALL, "");
assert(p);
wchar_t data[N];
wchar_t *s = fgetws(data, N, stdin);
assert(s);
int i = printf("%ls\n", data);
assert(i == 2);
i = fclose(stdin);
assert(i == 0);
return 0;
}

How to extract various integers from a string in C?

I was wondering how to extract various numbers from a string. I understand that strtol works, however it appears to only work for the first digit.
Here is my code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(){
long v1, v2, v3;
char str[20] = "16,23";
char *d;
v1 = strtol(str, &d, 10);
v2 = strtol(str, &d, 10);
printf("string is %s\nv1 is:%i\nv2 is:%d\n",str , v1,v2);
return 0;
}
In this example I would like to output v1 = 16 and v2 = 23.
Another example, if the str was "12,23,34", I would like v3= 34
Thanks in advance :)
You can have many approaches. One of them is to make use of the endptr, populated by the previous strtol() call as the source of the next strtol().
Otherwise, for a better and flexible approach, you also have an option of using strtok() with a predefined delimiter (the , here) to get the tokens one by one and convert them to int or long (as you wish) until strtok() returns NULL.
Use long strtol(const char * nptr, char ** endptr, int base). The endptr allows for easy subsequent parsing as that is where parsing stopped.
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
int string_to_longs(const char *s) {
#define N 3
long v[N];
int i;
for (i=0; i<N; i++) {
errno = 0;
char *end;
v[i] = strtol(s, &end, 10);
if (errno) return -1; // overflow
if (s == end) return -1; // no conversion
printf("v[%d] = %ld\n", i, v[i]);
if (*end == 0) break; // we are done
if (*end != ',') return -1; // missing comma
s = (const char *) (end + 1);
}
return i;
}
int main(void) {
string_to_longs("16,23");
string_to_longs("12,23,34");
return 0;
}
strtol just converts a character array to a long int. It stops when it finds the first character that wouldn't make sense into interpreting an integer from.
There is a function in string.h named strtok which helps you tokenize a string.
Beware that strtok mutates the original character array contents.

Iterate through char array and print chars

I am trying to print each char in a variable.
I can print the ANSI char number by changing to this printf("Value: %d\n", d[i]); but am failing to actually print the string character itself.
What I am doing wrong here?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int len = strlen(argv[1]);
char *d = malloc (strlen(argv[1])+1);
strcpy(d,argv[1]);
int i;
for(i=0;i<len;i++){
printf("Value: %s\n", (char)d[i]);
}
return 0;
}
You should use %c format to print characters in C. You are using %s, which requires to use pointer to the string, but in your case you are providing integer instead of pointer.
The below will work. You pass in the pointer to a string when using the token %s in printf.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int len = strlen(argv[1]);
char *d = malloc (strlen(argv[1])+1);
strcpy(d,argv[1]);
printf("Value: %s\n", d);
return 0;
}

snprintf in a loop does not work on linux

snprintf in a loop does not work on linux but it works properly on windows.
#include <stdio.h>
#include <stdlib.h>
int main( int argc, char **argv) {
char buffer[255] ={0};
for ( int i = 0; i < 10; i++) {
snprintf(buffer, 255, "%s:%x\0",buffer, i );
}
printf ( "BUFFER = %s\n", buffer );
return 0;
}
This code does not append existing buffer but only takes the last iteration value.
You can avoid the undefined behavior of using the buffer both as the target string and as an argument like this:
#include <stdio.h>
#include <stdlib.h>
int main( int argc, char **argv) {
char buffer[255] ={0};
int offset = 0;
for ( int i = 0; i < 10; i++) {
offset += snprintf(buffer + offset, 255 - offset, ":%x\0", i);
}
printf ( "BUFFER = %s\n", buffer );
return 0;
}
sprintf()'ing the result array to itself is undefined behaviour.
EDIT: if you want some code that works, here you are: use strcat() (or the safer strncat, etc. insert usual security discussion about buffer overflow here):
#include <stdio.h>
#include <stdlib.h>
int main( int argc, char **argv) {
char buffer[255] = { 0 };
char fmtbuf[64];
int i;
for (i = 0; i < 10; i++) {
snprintf(fmtbuf, 64, "%x", fmtbuf, i);
strcat(buffer, fmtbuf);
}
printf ("BUFFER = %s\n", buffer);
return 0;
}
Also note that printf() calls don't need the terminating zero to be written out manually -- it's automatically added.
snprintf does work as specified on Linux, but your code does not append it. Read the Note in the linked documentation!
You should not use as its arguments (after the format string) the destination.
If you want it to append, either ensure that you don't overflow your fixed buffer, or reallocate that buffer when it gets too small.
You could not write 'buffer' to itself by 'snprintf'.
The test code is as follow:
#include <stdio.h>
#include <stdlib.h>
#include <cstring>
int main( int argc, char **argv) {
char buffer[255] ={0};
for ( int i = 0; i < 10; i++) {
char tmp[255] = {0};
strcpy(tmp, buffer);
snprintf(buffer, 255, "%s:%x\0",tmp, i );
printf ( "BUFFER = %s\n", buffer );
}
printf ( "BUFFER = %s\n", buffer );
return 0;
}
The standard specifically states that this code is not expected to work. Firstly, the initial buffer argument is declared restrict, which means that it cannot alias another argument. Secondly, the standard has the following clause just for emphasis:
c99
7.19.6.5 The snprintf function
Description
2 - [...] If copying takes place between objects that overlap, the behavior is undefined.

Resources