What's the C library function to generate random string? - c

Is there a library function that creates a random string in the same way that mkstemp() creates a unique file name? What is it?

There's no standard function, but your OS might implement something. Have you considered searching through the manuals? Alternatively, this task is simple enough. I'd be tempted to use something like:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
void rand_str(char *, size_t);
int main(void) {
char str[] = { [41] = '\1' }; // make the last character non-zero so we can test based on it later
rand_str(str, sizeof str - 1);
assert(str[41] == '\0'); // test the correct insertion of string terminator
puts(str);
}
void rand_str(char *dest, size_t length) {
char charset[] = "0123456789"
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
while (length-- > 0) {
size_t index = (double) rand() / RAND_MAX * (sizeof charset - 1);
*dest++ = charset[index];
}
*dest = '\0';
}
This has the neat benefit of working correctly on EBCDIC systems, and being able to accommodate virtually any character set. I haven't added any of the following characters into the character set, because it seems clear that you want strings that could be filenames:
":;?#[\]^_`{|}"
I figured many of those characters could be invalid in filenames on various OSes.

There's no build in API, you may use (on *x system) /dev/urandom like:
FILE *f = fopen( "/dev/urandom", "r");
if( !f) ...
fread( binary_string, string_length, f);
fclose(f);
Note that this will create binary data, not string data so you'll may have to filter it afterwards.
You may also use standard pseudorandom generator rand():
#include <time.h>
#include <stdlib.h>
// In main:
srand(time(NULL));
for( int i = 0; i < string_length; ++i){
string[i] = '0' + rand()%72; // starting on '0', ending on '}'
}
And if you need really random string you need to google generating random sequence cryptography which is one of cryptography's difficult problems which still hasn't perfect solution :)

Related

Count the amount of individual characters (vowels) within a string in C

I've just started programming in C, and I have to create a program that counts how many vowels a string has. So far I have this:
int a;
int len = strlen(text)-1
for(a=0;a==len;++a){
if(text[a]=='a'){
++vocals;}
I'm clueless on what's wrong, because it will always print 0. I understand my code as:
starting on the first char until the last one before \0,
compare them to 'a', and if they do equal, add one to the counter.
What's wrong with my code?
Check your tutorials or textbook on the syntax and semantics of the for loop.
It requires a continuation condition, i.e. "loop as long as this is true".
So in your code you should change to:
for(a=0; a<len; ++a)
change this
for(a=0;a==len;++a)
to
for(a=0;a<=len;++a)
first iteration a is not equal to len so it will never enter the loop. you want to iterate over this for loop as long as a is lesser of eual to len, second statement does precisely that.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
char* text = "this is a test";
int i, vocals;
int len = strlen(text);
for(i=0;i<len;++i){
if(text[i]=='a'||text[i]=='e'||text[i]=='i'||text[i]=='o'||text[i]=='u')
++vocals;
}
printf("%d\n", vocals);
}
This is a working little program.
Let's look at the main together:
First we declare a char arrays, since you omitted that part i assume your string is correctly formed.
The for loop continues till i becames equal to len. It's a good programming practice to use < or > instead of != or == to increment the strength of the code. Anyway since it's a small program you can even use != which means "Execute the for loop till i becames equal to len"
In the if statement we are just checking if the current character is equal to 'a' or 'e' or 'i' or 'o' or 'u'. As you may now guess || operator means or.
EDIT:
There are a lot of more efficient (and complex) way to do this. For example using Regular Expression. If you're interested there are a lot of good tutorial online, for example this
This code snippet
int a;
int len = strlen(text)-1
for(a=0;a==len;++a){
if(text[a]=='a'){
++vocals;}
does not make great sense.
For example the character 'a' is not the only vowel, the condition a == len is evaluated to true only when the string contains just one character.
You can write a separate function that counts vowels in a string.
Here is a demonstrative program.
#include <stdio.h>
#include <ctype.h>
#include <string.h>
size_t count_vowels( const char *s )
{
const char *vowels = "aeiou";
size_t count = 0;
for ( ; *s; ++s )
{
if ( strchr( vowels, tolower( ( unsigned char )*s ) ) )
{
++count;
}
}
return count;
}
int main(void)
{
char s[] = "Hello Pelput";
printf( "There are %zu vowels in the string\n\"%s\"\n",
count_vowels( s ), s );
return 0;
}
The program output is
There are 4 vowels in the string
"Hello Pelput"

Convert buffer to array of 8-bit values and back in C

I would like to write a program in C that gets the file content via stdin and reads it line by line and, for each line, converts it to an array of 8-bit integer values.
I also would like to be able to do the reverse process. After working with my array of 8-bit values, I would like to convert it again to "lines" that would be organized as a new buffer.
So basically, I would like to convert a char * line to an int array[] and back (an int array[] to a char * line) while keeping the consistency, so when I create the file again out of the conversions, the file is valid (and by valid I mean, the conversion from int array[] to char * line generates the same content of the original char * line, while reading each line of the stdin.
My code is currently as follows:
#include <stdio.h>
#include <stdlib.h>
int main() {
FILE *stream;
char *line = NULL;
size_t len = 0;
ssize_t read;
stream = stdin;
if (stream == NULL)
exit(EXIT_FAILURE);
while ((read = getline(&line, &len, stream)) != -1) {
char * array = line_to_array(line);
// here I include the rest of my code
// where I am going to use the generated array
// ...
}
free(line);
fclose(stream);
exit(EXIT_SUCCESS);
}
The line_to_array function would be the one to convert the "line" content to the array of integers. In a second file, I would just do the opposite.
The mechanics of the process would be like this:
The first program (first.c) would receive a file content via stdin. By reading it using getline, I would have each line to convert to an array of integers and send each line to a second program (second.c) that would convert each array to a char * buffer again and the reconstruct the file.
In the terminal, I would run it like this:
./first | ./second
I appreciate any help on this matter.
Thank you.
I believe you may already know that a name of array is a kind of constant pointer. You could verify the fact from following code:
char hello[] = "hello world!";
for( int idx=0; *(hello + idx) != 0; idx++ )
{
printf("%c", *(hello + idx));
}
printf("\n");
So, there are no reason to convert character pointer to array. For your information, A char variable is a 8bit data in C, this can contain a integer value which is represent a character: 65 represent 'A' in ASCII code.
Secondly, this link may help you to understand how to convert between c string and std::string.
On second thought, may your input file is UNICODE or UTF-8 encoded file which is using multi-byte character code. In that case, you may not able to use getline() to read the string from the file. If so, please refer this question: Reading unicode characters.
I wish following code assist you to understand char type, array and pointer in C/C++:
std::string hello("Hello world");
const char *ptr = hello.c_str();
for( int idx=0; idx < hello.size(); idx++ )
{
printf("%3d ", *(ptr + idx));
}
printf("\n");
std::string hello("Hello world");
const char *ptr = hello.c_str();
for( int idx=0; idx < hello.size(); idx++ )
{
printf("%3d ", ptr[idx]);
}
printf("\n");

Converting Unicode codepoints to UTF-8 in C using iconv

I want to convert a 32-bit value, which represents a Unicode codepoint, into a sequence of chars which is the utf-8 encoded string containing only the character corresponding to the codepoint.
For example, I want to turn the value 955 into the utf-8 encoded string "λ".
I tried to do this using iconv, but I could not get the desired result. Here is the code that I wrote:
#include <stdio.h>
#include <iconv.h>
#include <stdint.h>
int main(void)
{
uint32_t codepoint = U'λ';
char *input = (char *) &codepoint;
size_t in_size = 2; // lower-case lambda is a 16-bit character (0x3BB = 955)
char output_buffer[10];
char *output = output_buffer;
size_t out_size = 10;
iconv_t cd = iconv_open("UTF-8", "UTF-32");
iconv(cd, &input, &in_size, &output, &out_size);
puts(output_buffer);
return 0;
}
When I run it, only a newline is printed (puts automatically prints a newline,-- the first byte of outout_buffer is '\0').
What is wrong with my understanding or my implementation?
As said by minitech, you must use size = 4 for UTF32 in an uint32_t, and you must preset the buffer to null to have the terminating null after conversion.
This code works on Ubuntu :
#include <stdio.h>
#include <iconv.h>
#include <stdint.h>
#include <memory.h>
int main(void)
{
uint32_t codepoint = 955;
char *input = (char *) &codepoint;
size_t in_size = 4; // lower-case lambda is a 16-bit character (0x3BB = 955)
char output_buffer[10];
memset(output_buffer, 0, sizeof(output_buffer));
char *output = output_buffer;
size_t out_size = 10;
iconv_t cd = iconv_open("UTF-8", "UTF-32");
iconv(cd, &input, &in_size, &output, &out_size);
puts(output_buffer);
return 0;
}
Two problems:
Since you’re using UTF-32, you need to specify 4 bytes. The “lower-case lambda is a 16-bit character (0x3BB = 955)” comment isn’t true for a 4-byte fixed-width encoding; it’s 0x000003bb. Set size_t in_size = 4;.
iconv doesn’t add null terminators for you; it adjusts the pointers it’s given. You’ll want to add your own before calling puts.
*output = '\0';
puts(output_buffer);

Is it possible to get the number of elements currently stored in an array in C?

I know it's possible to use the sizeof function to get the size, but it doesn't get a true count of the array length. If I set an array of int 50 and I stored only 10 numbers in there, I would want to get 10 as the number of elements, but of course that won't happen. I know this is definitely a trivial question, but bear with me here and help me on this if it is possible.
My code so far takes an entire sentence and stores it in an array.
#include <stdio.h>
#include <string.h>
int main()
{
int i=0;
char array[50]={0};
fgets(array, 50, stdin);
int len = sizeof(array); // it doesn't work :((((((
for(i=0; i<len; i++)
{
printf("%c\n", array[i]);
}
return 0;
}
As you guys can see, if the user decides to only enter a word of lets say "Bobby Foo" then I would want len number of 9 including the space, but the sizeof function only gets length of the size of the array declared which is 50.. >.>..
Q: Is it possible to get the number of elements currently stored in an array in C?
Short answer: No. You need to track this information yourself.
You happen to be using fgets() with a character array. Since in this case you're getting a C "string", you can use the C function strlen().
It's worth noting that fgets() will also return a newline - so your string might be a one (Mac, Linux) or two (DOS/Windows) characters longer than you expect.
PS:
Here is a bit more about C strings, including the concept of "null termination" (if you're not already familiar with them):
http://www.cprogramming.com/tutorial/c/lesson9.html
Use strlen to get the size of the array. You need to include string.h.
sizeof() is not a function it is an operator. When sizeof is applied to the name of a static array (not allocated through malloc), the result is the size in bytes of the whole array.
If you are using fgets, then you need to remove \n from the string. A simple way would be:
array[strlen(array) - 1] = '\0';
A quick example:
#include <stdio.h>
#include <string.h>
#include <stddef.h>
int main()
{
int i=0;
char array[50]={0};
char *p;
fgets(array, 50, stdin);
//Remove `\n` from the array.
if ((p=strchr(array, '\n')) != NULL)
*p = '\0';
size_t len = strlen(array); // Use strlen to find the length of string
for(i=0; i<len; i++)
{
printf("%c\n", array[i]);
}
return 0;
}

Simple way to extract part of a file path?

I'm not very good at C, and I always get stuck on simple string manipulation tasks (that's why I love Perl!).
I have a string that contains a file path like "/Volumes/Media/Music/Arcade Fire/Black Mirror.aac". I need to extract the drive name ("Media" or preferably "/Volumes/Media") from that path.
Any help would be greatly appreciated, just as I try to return the favor on the Perl questions!
Jim
I think sscanf could be appropriate:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
void test(char const* path) {
int len;
if(sscanf(path, "/Volumes/%*[^/]%n", &len) != EOF) {
char *drive = malloc(len + 1);
strncpy(drive, path, len);
drive[len] = '\0';
printf("drive is %s\n", drive);
free(drive);
} else {
printf("match failure\n");
}
}
int main() {
test("/Volumes/Media/Foo");
test("/Volumes/Media");
test("/Volumes");
}
Output:
drive is /Volumes/Media
drive is /Volumes/Media
match failure
I think that you need to be a little more exact in the specification of your problem.
When you say that you want to extract "Media", do you mean everything between the second and third '/' character, or is there a more complex heuristic at work?
Also, is the string in a buffer that's suitable to be modified?
Typically the way to do this would be to use strchr or strstr one or more times to find a pointer to where you want to extract the substring from (say p), and a pointer to the character after the last character that you need to extract (say q), if the buffer is a temporary buffer that you don't mind destroying then you can just do *q = 0 and p will be a pointer to the required string. Otherwise you need to have a buffer of at least q - p + 1 chars ( +1 is to include space for the null terminator as well as the q - p interesting characters. e.g. char *buffer = malloc(q - p + 1); ) and you can extract the string with memcpy. e.g. memcpy(buffer, p, q - p + 1).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char * extractDriveName(const char *path, char separator, int maxLen)
{
char *outBuffer;
int outBufferSize, i, j;
int sepOcur;
outBufferSize = strlen(path) + 1;
outBufferSize = outBufferSize > maxLen ? maxLen : outBufferSize;
outBuffer = (char *) malloc(outBufferSize);
// Error allocating memory.
if(outBuffer == NULL)
return NULL;
memset(outBuffer, 0, outBufferSize);
for(i = 0, sepOcur = 0, j = 0; i < outBufferSize; i++)
{
if(path[i] == separator)
sepOcur ++;
if(sepOcur >= 0 && sepOcur < 3)
outBuffer[j++] = path[i];
else if(sepOcur == 3)
break;
}
// Don't forget to free the buffer if
return outBuffer;
}
int main(void)
{
char path [] = "/Volumes/Media/Music/Arcade Fire/Black Mirror.aac";
char * driveName = extractDriveName(path, '/', strlen(path) + 1);
if(driveName != NULL)
{
printf("Path location: '%s'\n", path);
printf("Drive name: '%s'\n", driveName);
free(driveName);
}
else
{
printf("Error allocating memory\n");
}
}
Output:
Path location: '/Volumes/Media/Music/Arcade Fire/Black Mirror.aac'
Drive name: '/Volumes/Media'
I think that the easiest way is to use strtok(). This function will split a string in tokens separated by one of the characters in the separators string.
If your original path is in str and you want the second part in part:
strtok(str, "/"); /* To get the first token */
part=strtok(NULL, "/"); /* To get the second token that you want */
Note that strtok() will change str, so it should not be a const. If you have a const string, you might use stdrup(), which is not standard but normally available, to create a copy.
Also note that strtok() is not thread safe.
You example makes it appear that you are working in a Macintosh environment. I suspect that there is an Apple API to get the volume on which a particular file resides.
Any reason not to use that?
Edit: Looking at your profile, I suspect I guessed wrong about your environment. I can't help you for windows. Good luck. I'll leave this here in case anyone is looking for the same answer on a Mac.
From Mac Forums I find "Getting the current working Volume name?" which seems to be the same question. There is a nice discussion there, but they dpn't seem to come to a single answer.
Google is your friend.
Another possibility: BSD Path to Volume Name & Vice-Versa at CocoaDev Forums.

Resources