A
arnuld
AIM: To convert a wide-character string into a character string
PROBLEM: (1) checking return value or errno.
(2) conversion just does not happen.
#include <stdio.h>
#include <stdlib.h>
#include <wchar.h>
#include <errno.h>
#include <string.h>
#include <locale.h>
#include <limits.h>
#ifndef __STDC_ISO_10646__
#define __STDC_ISO_10646__
#endif
enum {
VAL_SUCC = 0,
VAL_ERR = -1,
ERR_ENC = -101,
ERR_ERRNO_UNKNOWN = -102,
SIZE_INPUT = 1000
};
void setLocale(const char* t);
size_t WStr2CStr(char **s, const wchar_t* ws, const size_t len);
void getGermanLanguageFromFile(wchar_t arr[], const size_t len);
char* myMalloc(const size_t len);
int main(void)
{
int ret = 0;
wchar_t contents[SIZE_INPUT+1] = {0};
char* p = NULL;
size_t plen = 0;
setLocale("en_US.utf8");
getGermanLanguageFromFile(contents, SIZE_INPUT);
printf("Contents = {%ls}\n\n", contents);
plen = ret + 1;
printf("plen = %d\n", plen);
p = myMalloc(plen);
ret = WStr2CStr(&p, contents, plen);
if( ret <= 0)
{
printf("IN: %s @%d ERROR converting to characters: ERRNO = %d\n",
__FILE__, __LINE__, ret);
exit(EXIT_FAILURE);
}
printf("p = [%s]\n\n", p);
printf("W = %zu, Char = %zu\n", wcslen(contents), strlen(p));
free(p);
return 0;
}
char* myMalloc(const size_t len)
{
char* p = malloc(len * (sizeof *p));
if(NULL == p)
{
printf("IN: %s @%d Out of Memory\n", __FILE__, __LINE__);
exit(EXIT_FAILURE);
}
return p;
}
void setLocale(const char* t)
{
if(NULL == setlocale(LC_CTYPE, t))
{
printf("IN: %s @%d ERROR: can not set locale [%s]\n", __FILE__,
__LINE__, t);
exit(EXIT_FAILURE);
}
else
{
printf("IN: %s @%d Locale Set = [%s]\n", __FILE__, __LINE__, t);
}
}
/* Contents of german.txt: Megaupload-Gründer Schmitz gegen Kaution auf
freiem Fuß. News */
void getGermanLanguageFromFile(wchar_t arr[], const size_t len)
{
const char* filename = "german.txt";
FILE* fp;
wchar_t* retp;
fp = fopen(filename,"r");
if(NULL == fp)
{
printf("IN:%s @%d: ERROR [%s]Can not open (%s)\n",__FILE__,
__LINE__, strerror(errno), filename);
return;
}
errno = 0;
retp = fgetws(arr, len, fp);
if(NULL == retp)
{
if(feof(fp))
{
printf("IN: %s @%d Reading Error: [%s]\n", __FILE__, __LINE__,
strerror(errno));
}
else
{
printf("IN: %s @%d Reading Error: ERRNO = %d\n", __FILE__,
__LINE__, errno);
}
exit(EXIT_FAILURE);
}
}
size_t WStr2CStr(char **s, const wchar_t* ws, const size_t len)
{
int ret = VAL_ERR;
if(NULL == ws || NULL == s)
{
ret = VAL_ERR;
}
else
{
size_t r;
errno = 0;
r = wcstombs(*s, ws, len);
if(0 >= r)
{
if(EILSEQ == errno)
{
ret = ERR_ENC;
}
else if(0 == r)
{
printf("IN: %s @%d ERROR: ZERO bytes converted = %zu\n",
__FILE__, __LINE__, r);
ret = VAL_ERR;
}
else if(errno)
{
ret = ERR_ERRNO_UNKNOWN;
}
}
else
{
printf("IN: %s @%d bytes converted = %zu\n", __FILE__,
__LINE__, r);
ret = r;
}
}
return ret;
}
==================== OUTPUT ==============================
[arnuld@dune C]$ gcc -std=c99 -pedantic -Wall -Wextra convert.c
[arnuld@dune C]$ ./a.out
IN: convert.c @82 Locale Set = [en_US.utf8]
Contents = {Megaupload-Gründer Schmitz gegen Kaution auf freiem Fuß. News}
plen = 1
IN: convert.c @151 bytes converted = 1
p = [M]
W = 61, Char = 1
[arnuld@dune C]$
I searched archives and came across this piece of code where poster calls
wcstombs() 2 times, first to calculate characters (using NULL argument)
and then to really do the conversion. I wonder if that is the way wcstombs
() was supposed to use (because it works while mine does not):
size_t n = wcstombs(NULL, src, 0);
char *dst = malloc(n + 1);
if(dst == NULL)
{
fprintf(stderr, "memory allocation failed\n");
return NULL;
}
if(wcstombs(dst, src, n + 1) != n)
{
fprintf(stderr, "conversion failed\n");
free(dst);
return NULL;
}
PROBLEM: (1) checking return value or errno.
(2) conversion just does not happen.
#include <stdio.h>
#include <stdlib.h>
#include <wchar.h>
#include <errno.h>
#include <string.h>
#include <locale.h>
#include <limits.h>
#ifndef __STDC_ISO_10646__
#define __STDC_ISO_10646__
#endif
enum {
VAL_SUCC = 0,
VAL_ERR = -1,
ERR_ENC = -101,
ERR_ERRNO_UNKNOWN = -102,
SIZE_INPUT = 1000
};
void setLocale(const char* t);
size_t WStr2CStr(char **s, const wchar_t* ws, const size_t len);
void getGermanLanguageFromFile(wchar_t arr[], const size_t len);
char* myMalloc(const size_t len);
int main(void)
{
int ret = 0;
wchar_t contents[SIZE_INPUT+1] = {0};
char* p = NULL;
size_t plen = 0;
setLocale("en_US.utf8");
getGermanLanguageFromFile(contents, SIZE_INPUT);
printf("Contents = {%ls}\n\n", contents);
plen = ret + 1;
printf("plen = %d\n", plen);
p = myMalloc(plen);
ret = WStr2CStr(&p, contents, plen);
if( ret <= 0)
{
printf("IN: %s @%d ERROR converting to characters: ERRNO = %d\n",
__FILE__, __LINE__, ret);
exit(EXIT_FAILURE);
}
printf("p = [%s]\n\n", p);
printf("W = %zu, Char = %zu\n", wcslen(contents), strlen(p));
free(p);
return 0;
}
char* myMalloc(const size_t len)
{
char* p = malloc(len * (sizeof *p));
if(NULL == p)
{
printf("IN: %s @%d Out of Memory\n", __FILE__, __LINE__);
exit(EXIT_FAILURE);
}
return p;
}
void setLocale(const char* t)
{
if(NULL == setlocale(LC_CTYPE, t))
{
printf("IN: %s @%d ERROR: can not set locale [%s]\n", __FILE__,
__LINE__, t);
exit(EXIT_FAILURE);
}
else
{
printf("IN: %s @%d Locale Set = [%s]\n", __FILE__, __LINE__, t);
}
}
/* Contents of german.txt: Megaupload-Gründer Schmitz gegen Kaution auf
freiem Fuß. News */
void getGermanLanguageFromFile(wchar_t arr[], const size_t len)
{
const char* filename = "german.txt";
FILE* fp;
wchar_t* retp;
fp = fopen(filename,"r");
if(NULL == fp)
{
printf("IN:%s @%d: ERROR [%s]Can not open (%s)\n",__FILE__,
__LINE__, strerror(errno), filename);
return;
}
errno = 0;
retp = fgetws(arr, len, fp);
if(NULL == retp)
{
if(feof(fp))
{
printf("IN: %s @%d Reading Error: [%s]\n", __FILE__, __LINE__,
strerror(errno));
}
else
{
printf("IN: %s @%d Reading Error: ERRNO = %d\n", __FILE__,
__LINE__, errno);
}
exit(EXIT_FAILURE);
}
}
size_t WStr2CStr(char **s, const wchar_t* ws, const size_t len)
{
int ret = VAL_ERR;
if(NULL == ws || NULL == s)
{
ret = VAL_ERR;
}
else
{
size_t r;
errno = 0;
r = wcstombs(*s, ws, len);
if(0 >= r)
{
if(EILSEQ == errno)
{
ret = ERR_ENC;
}
else if(0 == r)
{
printf("IN: %s @%d ERROR: ZERO bytes converted = %zu\n",
__FILE__, __LINE__, r);
ret = VAL_ERR;
}
else if(errno)
{
ret = ERR_ERRNO_UNKNOWN;
}
}
else
{
printf("IN: %s @%d bytes converted = %zu\n", __FILE__,
__LINE__, r);
ret = r;
}
}
return ret;
}
==================== OUTPUT ==============================
[arnuld@dune C]$ gcc -std=c99 -pedantic -Wall -Wextra convert.c
[arnuld@dune C]$ ./a.out
IN: convert.c @82 Locale Set = [en_US.utf8]
Contents = {Megaupload-Gründer Schmitz gegen Kaution auf freiem Fuß. News}
plen = 1
IN: convert.c @151 bytes converted = 1
p = [M]
W = 61, Char = 1
[arnuld@dune C]$
I searched archives and came across this piece of code where poster calls
wcstombs() 2 times, first to calculate characters (using NULL argument)
and then to really do the conversion. I wonder if that is the way wcstombs
() was supposed to use (because it works while mine does not):
size_t n = wcstombs(NULL, src, 0);
char *dst = malloc(n + 1);
if(dst == NULL)
{
fprintf(stderr, "memory allocation failed\n");
return NULL;
}
if(wcstombs(dst, src, n + 1) != n)
{
fprintf(stderr, "conversion failed\n");
free(dst);
return NULL;
}