Accept non ASCII characters - c

Consider this program:
#include <stdio.h>
int main(int argc, char* argv[]) {
printf("%s\n", argv[1]);
return 0;
}
I compile it like this:
x86_64-w64-mingw32-gcc -o alpha alpha.c
The problem is if I give it a non ASCII argument:
$ ./alpha róisín
r�is�n
How can I write and/or compile this program such that it accepts non ASCII
characters? To respond to alk: no, the program is printing wrongly. See
this example:
$ echo Ω | od -t x1c
0000000 ce a9 0a
316 251 \n
0000003
$ ./alpha Ω | od -t x1c
0000000 4f 0d 0a
O \r \n
0000003

The easiest way to do this is with wmain:
#include <fcntl.h>
#include <stdio.h>
int wmain (int argc, wchar_t** argv) {
_setmode(_fileno(stdout), _O_WTEXT);
wprintf(L"%s\n", argv[1]);
return 0;
}
It can also be done with GetCommandLineW; here is a simple version of the code
found at the HandBrake repo:
#include <stdio.h>
#include <windows.h>
int get_argv_utf8(int* argc_ptr, char*** argv_ptr) {
int argc;
char** argv;
wchar_t** argv_utf16 = CommandLineToArgvW(GetCommandLineW(), &argc);
int i;
int offset = (argc + 1) * sizeof(char*);
int size = offset;
for (i = 0; i < argc; i++)
size += WideCharToMultiByte(CP_UTF8, 0, argv_utf16[i], -1, 0, 0, 0, 0);
argv = malloc(size);
for (i = 0; i < argc; i++) {
argv[i] = (char*) argv + offset;
offset += WideCharToMultiByte(CP_UTF8, 0, argv_utf16[i], -1,
argv[i], size-offset, 0, 0);
}
*argc_ptr = argc;
*argv_ptr = argv;
return 0;
}
int main(int argc, char** argv) {
get_argv_utf8(&argc, &argv);
printf("%s\n", argv[1]);
return 0;
}

Since you're using MinGW (actually MinGW-w64, but that shouldn't matter in this case), you have access to the Windows API, so the following should work for you. It could probably be cleaner and actually tested properly, but it should provide a good idea at the least:
#define _WIN32_WINNT 0x0600
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <windows.h>
int main (void)
{
int argc;
int i;
LPWSTR *argv;
argv = CommandLineToArgvW(GetCommandLineW(), &argc);
if (argv == NULL)
{
FormatMessageA(
(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS),
NULL,
GetLastError(),
0,
(LPWSTR)&error, 0,
NULL);
fprintf(stderr, error);
fprintf(stderr, "\n");
LocalFree(error);
return EXIT_FAILURE;
}
for (i = 0; i < argc; ++i)
wprintf(L"argv[%d]: %ls\n", i, argv[i]);
// You must free argv using LocalFree!
LocalFree(argv);
return 0;
}
Bear in mind this one issue with it: Windows will not compose your strings for you. I use my own Windows keyboard layout that uses combining characters (I'm weird), so when I type
example -o àlf
in my Windows Command Prompt, I get the following output:
argv[0]: example
argv[1]: -o
argv[2]: a\u0300lf
The a\u0300 is U+0061 (LATIN SMALL LETTER A) followed by a representation of the Unicode code point U+0300 (COMBINING GRAVE ACCENT). If I instead use
example -o àlf
which uses the precomposed character U+00E0 (LATIN SMALL LETTER A WITH GRAVE), the output would have differed:
argv[0]: example
argv[1]: -o
argv[2]: \u00E0lf
where \u00E0 is a representation of the precomposed character à represented by Unicode code point U+00E0. However, while I may be an odd person for doing this, Vietnamese code page 1258 actually includes combining characters. This shouldn't affect filename handling ordinarily, but there may be some difficulty encountered.
For arguments that are just strings, you may want to look into normalization with the NormalizeString function. The documentation and examples linked in it should help you to understand how the function works. Normalization and a few other things in Unicode can be a long journey, but if this sort of thing excites you, it's also a fun journey.

Try compiling and running the following program:
#include <stdio.h>
int main()
{
int i = 0;
for( i=0; i<256; i++){
printf("\nASCII Character #%d:%c ", i, i);
}
printf("\n");
return 0;
}
In your output you should see those little question marks from number 128 and onward. FYI I am using Ubuntu, and when I compile and run this program (whith GNOME Terminal) this happens to me as well.
However, if I go to Terminal > Set character encoding... and select Western (WINDOWS-1252) as opposed to Unicode (UTF-8), and rerun the program, the extended ASCII characters display properly.
I don't know the exact steps for Windows/MinGW, but, in short, changing the character encoding should fix your problem.

Related

How do i add up all elements of a command line argument

here is my code
#include <stdio.h>
#include <stdlib.h>
int main(int argc,char* argv[])
{
int a;
for(int i=1;i<=argc;i++){
a+=atoi(argv[i]);
}
printf ("%d",a);
}
I keep getting segmentation faults but i am trying to add up all elements of the command line so for example ./a.out 5 6 7 would give 18 as the output, cheers.
The problem (with the crash) is the loop itself:
for(int i=1;i<=argc;i++)
The argc argument is the number of arguments passed to the program, including the "program name" at argv[0]. So valid indexes for the actual arguments are argv[1] to argv[argc - 1].
Furthermore the argv array is terminated by a null pointer, which will be at argv[argc].
Since you include argv[argc] in your loop you pass a null pointer to atoi which leads to undefined behavior and likely crashes.
The simple solution is to use less-than < instead of less-than-or-equal as the loop condition:
for(int i=1;i<argc;i++)
You never initialized a to 0. Also, use strtol() function.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
int a = 0;
for (int i = 1; i < argc; i++) {
a += strtol(argv[i], NULL, 10);
}
printf("%d\n", a);
return EXIT_SUCCESS;
}

Storing characters in array using pointers

I am supposed to create an array with the fixed size (let’s say 5x5). I am supposed to fill it with words typed as command line parameters. I can use only pointers. Obviously I have to create two dimensional array[5][5]. I can’t use more than 25 letters ( I will make if statements ). I am going replace white space with some symbol ($ or something). The problem is I don’t know how to connect those command line parameters with array using only pointers.
You need to use the argc and argv arguments from the main function.
Here is an example.
#include <stdio.h>
int main(int argc, char *argv[])
{
for (unsigned i = 1; i < argc; i++)
{
printf("Word %u is: %s\n", i, argv[i]);
}
return 0;
}
You compile it using gcc main.c -o a.exe.
And run it using a.exe hello world.
Edit:
Further to your comment.
You can create an array of pointers like so:
#include <stdio.h>
#include <string.h>
#include <stddef.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char *my_array_of_strings[5]; // up to 5 strings
// populate your array
for (unsigned i = 1; i < argc; i++)
{
my_array_of_strings[i - 1] = malloc(strlen(argv[i]) + 1);
if (NULL == my_array_of_strings[i - 1])
{
printf("oh no, memory failure");
break;
}
memcpy(my_array_of_strings[i - 1], argv[i], strlen(argv[i]) + 1);
printf("word is %s\n", my_array_of_strings[i - 1]);
}
return 0;
}

C in Linux - using execle() to output an environment variable?

Program 1
In program 1 I have attempted to create the sole environment variable envar putting it in the env array which is passed to the execle function for the environments creation which program 2 will be run in.
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[]){
int ret;
char envar[] = "Big ol' environment variable ;D";
char *env[2] = {envar, 0};
ret = execle("./exec_test1.1", "exec_test1.1", 0, env);
printf("my prog failed ret = %d", ret);
return 0;
}
Program 2
I intended this code in the same directory to retrieve the environment variable envar on execution and to print it. However I the output in its place is null "memes and dis (null)" I have searched but can't see my mistake. Program two is almost identical to another I found for the same purpose so I assume my mistake is in program one.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]){
char *envptr = getenv("envar");
printf("memes and dis %s\n", envptr);
return 0;
}
Thanks
You have wrong envar variable format - it must be NAME=VALUE. So fixing program 1 to:
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int ret;
char envar[] = "envar=Big ol' environment variable ;D";
char *env[2] = {envar, 0};
ret = execle("./exec_test1.1", "exec_test1.1", 0, env);
printf("my prog failed ret = %d", ret);
return 0;
}
should make it work.
(I also took some liberty and formatted the code to make it more readable)

SHA_256 functions corrupting memory space

I've been trying to use the SHA_256 functions in sha256.h on a FreeBSD 9.1 system but it seems to be corrupting memory space of my program causing all kinds of manic behavior. I wrote up a quick program to just to play with those functions and still am having problems.
In the example below, int i is changed when I call SHA256_Init(), as shown by the output from the printf() statements surrounding it.
This is what I get running the code.
$ ./miner "hello world"
i = 0
i = 32
0000000032 9010a9cf81ce2c28a642fd03ddf6da5790c65c30cd4a148c4257d3fe488bacc7
Why is this value changing to 32? Am I missing something? The code is below...
#include <sha256.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#define DIFFICULTY 0
int main(int argc, const char **argv) {
uint nonce, i, j;
SHA256_CTX ctx;
size_t arglen;
unsigned char digest[32];
char * data;
if(argc < 1) exit(1);
arglen = strlen(argv[1]);
data = malloc(arglen + 1);
char digestStr[65];
i = 0;
do {
nonce = i;
strncpy(data, argv[1], arglen + 1);
printf("i = %i\n", i);
SHA256_Init(&ctx);
printf("i = %i\n", i);
SHA256_Update(&ctx, data, arglen);
SHA256_Update(&ctx, (unsigned char *) &nonce, sizeof(nonce));
SHA256_Final(digest, &ctx);
SHA256_End(&ctx, digestStr);
printf("%010i\t%s\n", i, digestStr);
j = 0;
while(j < 32 && digest[j] == '\0') {
j++;
}
i++;
} while(j < DIFFICULTY);
free(data);
return 0;
}
I just had this exact same problem and solved it.
The issue is that your are including a different header in your code than the SHA2 library you linked into your application is using.
In my case the SHA256_CTX struct was a different size in the openSSL library. The openSSL library's struct was 8 bytes bigger than the struct length in the file.
The function SHA256_Init(&ctx) does a memset on the SHA256_CTX struct which then corrupts 8 extra random bytes after the struct. I say random because it will do different things in a release vs debug build because the optimizing compiler will move your variables around.

Basic C Array function

I am new here and programming. I need to write a function to be able to divide a sentence through the desired input and output them separately.
Such as the input is "Hello, How are you..." it's 23 characters and the other input is numerical "6".
Thus, I want to print it as "Hello," and "How are you..."
I think it would be best to use arrays... However, I cannot write the function. I hope someone could help me..
By the way, if I wanted place the function in a header file, how can I manage that.
Thanks a lot...
First the header file that declares the split_string function. (As you are new to programming, I put detailed comments):
/* Always begin a header file with the "Include guard" so that
multiple inclusions of the same header file by different source files
will not cause "duplicate definition" errors at compile time. */
#ifndef _SPLIT_STRING_H_
#define _SPLIT_STRING_H_
/* Prints the string `s` on two lines by inserting the newline at `split_at`.
void split_string (const char* s, int split_at);
#endif
The following C file makes use of split_string:
// test.c
#include <stdio.h>
#include <string.h> /* for strlen */
#include <stdlib.h> /* for atoi */
#include "split_string.h"
int main (int argc, char** argv)
{
/* Pass the first and second commandline arguments to
split_string. Note that the second argument is converted to an
int by passing it to atoi. */
split_string (argv[1], atoi (argv[2]));
return 0;
}
void split_string (const char* s, int split_at)
{
size_t i;
int j = 0;
size_t len = strlen (s);
for (i = 0; i < len; ++i)
{
/* If j has reached split_at, print a newline, i.e split the string.
Otherwise increment j, only if it is >= 0. Thus we can make sure
that the newline printed only once by setting j to -1. */
if (j >= split_at)
{
printf ("\n");
j = -1;
}
else
{
if (j >= 0)
++j;
}
printf ("%c", s[i]);
}
}
You can compile and run the program as (assuming you are using the GNU C Compiler):
$ gcc -o test test.c
$ ./test "hello world" 5
hello
world
First of all string in C is a char * which is an array of char already:
char *msg = "Hello, World!";
int i;
for(i=0; i<strlen(msg); ++i)
{
char c = msg[i];
// Do something
}
If you want to put your function in the header file just define it as inline

Resources