I'm trying to create a program that generates random words from Katakana (Japanese syllables).
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <wchar.h>
#include <locale.h>
char* word;
char *kata[] = {"ア", "イ", "ウ", "エ", "オ", "カ", "キ", "ク", "ケ", "コ", "サ", "シ", "ス","セ","ソ","タ","チ","ツ","テ","ト","ナ","ニ","ヌ",
"ネ","ノ","ハ","ヒ","フ","ヘ","ホ","マ","ミ","ム","メ","モ","ヤ","ユ","ヨ","ラ","リ","ル","レ","ロ","ワ","ヲ","ン","ガ","ギ",
"グ","ゲ","ゴ","ザ","ジ","ズ","ゼ","ゾ","ダ","ヂ","ヅ","デ","ド","バ","ビ","ブ","ベ","ボ","パ","ピ","プ","ペ","ポ","ャ","ュ",
"ョ","ヴ","ァ","ィ","ゥ","ェ","ォ"};
int x = 0;
void generator (int length) {
for (int z=0; z<length; z++) {
x = rand() % sizeof(*kata);
concat(word,kata[x]);
}
}
int main (void) {
srand((unsigned) time(NULL));
int length = rand() % 5 + 2;
generator(length);
puts(word);
}
word is the String that I want to get printed, and kata is a Char Array containing Katakana. However, if I don't include the "*" to make the array an String array, C complains that there are multiple characters in a char. The rest of the code works fine in my testing.
I'm using BoUoW which has a full Ubuntu environment on Windows, so I don't think that's the problem, but rather how I'm putting the String array into the String.
I've done a similar program in Java in about an hour and this has taken me much longer. Although that's probably because I'm new to C.
Lot of check should be added (overflow on word for example)
The number of element on kata is the sizeof kata / sizeof an element you can do a macro countof
strcat is the function you need.
The idea is something like
char *kata[] = {"ア", "イ", "ウ", "エ", "オ", "カ", "キ", "ク", "ケ", "コ", "サ", "シ", "ス","セ","ソ","タ","チ","ツ","テ","ト","ナ","ニ","ヌ
",
"ネ","ノ","ハ","ヒ","フ","ヘ","ホ","マ","ミ","ム","メ","モ","ヤ","ユ","ヨ","ラ","リ","ル","レ","ロ","ワ","ヲ","ン","ガ","ギ",
"グ","ゲ","ゴ","ザ","ジ","ズ","ゼ","ゾ","ダ","ヂ","ヅ","デ","ド","バ","ビ","ブ","ベ","ボ","パ","ピ","プ","ペ","ポ","ャ","ュ",
"ョ","ヴ","ァ","ィ","ゥ","ェ","ォ"};
int x = 0;
static void generator (int nb, char *word, size_t n) {
word[0] = '\0';
while (nb-- > 0) {
x = rand() % (sizeof(kata) / sizeof(char*));
strcat(word, kata[x]);
}
}
int main (void) {
char word[64];
srand((unsigned) time(NULL));
int nb = rand() % 5 + 2;
generator(nb, word, sizeof(word));
puts(word);
return 0;
}
Which book are you reading? The reason I ask is that you've encountered a series of categorical errors regarding the fundamentals of C which people who read good books don't usually encounter. I can recommend K&R2E to someone who's already experienced programming from another language.
word is the String ...
Not in the code you've shown us, no... word contains a null pointer, and in your code you're assigning into that null pointer. Bad news :(
Stop confusing the concept of strings (which are a category of values) with pointers (which are a category of types).
A string is a sequence of character values that terminates at the first '\0'. That's a value. Strings are stored within arrays; an array is a category of type.
A pointer denotes a type which has values that point at/into arrays (which might or might not contain a string), functions or at nothing (which are null pointers).
... kata is a Char Array containing Katakana ...
Again, this isn't the case. kata is an array of char *. char * is not a character type; it's a character pointer type!
However, if I don't include the "*" to make the array an String array, C complains that there are multiple characters in a char.
I'm not sure what you expect. Since the type of a string literal expression such as "ア" is a char[n] (character array type) which gets converted to a char * (character pointer type) with a value pointing at the first character, and you store multiple of those in an array, the type of your array needs to be char *[m]. The * is necessary! I don't see a problem here.
I do see other problems, however. Firstly, concat isn't defined. You've not asked a question about this, so here's the definition I'll use to fill in the blanks:
void concat(char *dest, char *src) {
strcat(dest, src); // `strcat` is from `<string.h>`
}
sizeof(*kata) retrieves the size of a char *, which is commonly four or eight... so rand() % sizeof(*kata) will equate to rand() % 4 or rand % 8 on common systems. Perhaps you meant rand() % (sizeof kata / sizeof *kata). More on that later...
As I mentioned earlier, word is a null pointer and you can't assign into such a pointer. You need to make it point at something. You can do this by:
Using the &address-of operator on a variable. I assume this isn't suitable for you, as you'll want your pointer to point at a sequence of more than one object, but this is helpful to explain anyway. For example:
int x;
int *pointer_to_x = &x;
Declaring an array, and using the identifier of the array, possibly in conjunction with the + addition operator to point at an element in the array. For example:
int array[42];
int *pointer_to_first = array + 0;
int *pointer_to_second = array + 1;
Calling malloc, realloc, calloc or some other function that returns a pointer to a suitably sized object. For example:
int *pointer_to_whatever = malloc(42 * sizeof *pointer_to_whatever);
// Remember to free(pointer_to_whatever) ONCE when you're done with it
int isn't really appropriate for storing array indexes or lengths; you're better off using size_t as that doesn't have negative values which doesn't just eliminate some bugs, but also makes your code a little more efficient.
rand() % sizeof(*kata) isn't very random.
In fact, it's quite predictable. By reseeding with the same seed, another program can reproduce that exact sequence. By iterating on seeds, starting with seed = time(NULL) and moving backwards in time, it's easy enough to prove that this is no less predictable than a single int value, despite the fact that it is in fact multiple character values.
Additionally, rand tends to introduce biases, especially when you use the % operator to reduce it. You need to remove the bias. You could do this by first assigning your random number to a double, then dividing it by RAND_MAX + 1.0 like so:
double rand_double(void) {
return rand() / (RAND_MAX + 1.0);
}
With this function returning a value between 0.0 and 1.0 (excluding 1.0), you should be able to use rand_double() * (sizeof kata / sizeof *kata) for example, and this will be better... but the bias is still there; it's just reduced. To eliminate the bias, you need to consider that rand returns a sequence of values, each of which lie within [0..RAND_MAX], and that your range doesn't divide evenly into that range; the remainder of the division is a huge part of your bias. You need to take the range, and truncate it down to something that does divide evenly! That is, make a function that wraps rand and discards values greater than RAND_MAX - (RAND_MAX % (sizeof kata / sizeof *kata))... I've described (and solved) this problem in a solution I posted on gist, so for your convenience here's an adaptation of that code:
unsigned int rand_range(unsigned int ceiling) {
int n;
do {
n = rand();
} while (RAND_MAX - n <= RAND_MAX % ceiling);
return n % ceiling;
}
This is better again, but you won't want to use anything rand-derived for security purposes, so don't use this for passwords! This is because of the attack described earlier, where people can go back in time by reseeding to produce values previously generated. Use a cryptographically secure random number generator for that.
hi i am making a programming language that will run on the nintendo gameboy in c
which is why you will see some functions like waitpad();
but this question is unrelated the the gameboy librarys
for some reason when ever i try to increment a certain variable in my main.c file:
#include <stdio.h>
#include <gb/gb.h>
#include "convert.h"
#include "display.h"
#include "input.h"
#include "functions.h"
#include "interpreter.h"
unsigned char cnt[5] = {1,2,3,4,5};//cnt is short for counters
unsigned char k = 0;
unsigned char running = 1;
unsigned char memory[2048];
unsigned char code[2048];
int main()
{
Clear_mem();
Clear_code();
while(running == 1) {
display(cnt[0],cnt[1],cnt[2],cnt[3],cnt[4]);
printf("cnt[0] = %d\n", cnt[0]);
cnt[0]++;//turns into -17918
printf("Press Start To Enter Next Character\n");
waitpad(J_START);
code[k] = input();
interpret(code[k]);
k++;
}
return 0;
}
cnt[0] turns into -17918
can anyone see any problem that would cause it to behave this way?
You ask if anyone sees a problem, well - yes, here is a problem:
unsigned char k = 0;
unsigned char running = 1;
unsigned char code[2048];
while(running == 1) {
code[k] = input();
k++;
}
If k >= 2048, then code[k] = ... will cause a memory-override.
After a memory-override, pretty much anything can happens (undefined behavior).
Having said that, the value of k can be larger than 2047 only if CHAR_BIT is larger than 11.
Add #include <limits.h> to your program and make sure that CHAR_BIT is not larger than 11.
You have to convert it to an integer, because that's what you're trying to print:
printf("cnt[0] = %d\n", (int) cnt[0]);
When you're using a variadic function like printf, you have to make sure you're passing the right type. Check your compiler warning settings, new compilers can easily detect these kind of problems.
if you want to print the character value of your character variable you should print it like this:
printf("cnt[0] = %c\n", cnt[0]);
If you print it using %d the expansion of the character to a size of int could be negative for characters over half a character's size (0x80 and up).
If you insist on printing it as an int cast the variable like this:
printf("cnt[0] = %d\n", (int)cnt[0]);
Ok,I am beginner in C.I was thought that for a array to hold to characters in need to declare it as:
char a[10];
So I will have 10 elements from (0 to 9)
but it is not working.It is giving me unwanted characters.Can you tell me the problem is.My code:
#include<stdio.h>
#include<stdlib.h>
int main(void)
{
printf("%s",rand_string());
}
int rand_string(void)
{
srand(time(NULL));
char a[7];
int e;
int d;
a[0]='l';
a[1]='o';
a[2]='n';
a[3]='g';
a[4]=' ';
d=(rand()%6) + 97;
a[5]=d;
e=(rand()%10) + 48;
a[6]=e;
printf("\n%s\n",a);
return a;
}
I get results like:
long f99
|/
What I expect:
long f9
Ok so in total I have 4 questions:
*How to fix the problem of unwanted characters and why is it giving unwated characters?
*Is my way of generating random numbers with limit ok?
*how to write the first 4 letters "long" in one line rather that for each line in an array?
*How to combine 2 strings?
You need to NULL terminate your string. Extend the array by one and add a[7] = 0; in there and you'll be set.
Editorial note: Your program has another big problem in that you are returning a pointer to a local variable. You may want to change rand_string to fill in a buffer provided by main instead. Here's a quick example with both of these modifications:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void rand_string(char a[8])
{
srand(time(NULL));
int e;
int d;
a[0]='l';
a[1]='o';
a[2]='n';
a[3]='g';
a[4]=' ';
d=(rand()%6) + 97;
a[5]=d;
e=(rand()%10) + 48;
a[6]=e;
a[7]=0;
printf("\n%s\n",a);
}
int main(void)
{
char buffer[8];
rand_string(buffer);
printf("%s", buffer);
return 0;
}
The first question is already answered by Carl Norum.
Is my way of generating random numbers with limit ok?
Yes, but defining a function would be nice, wouldn't it? Calling like a[0] = randomBetween(97, 102); is much more readable though.
EDIT: As in a comment above stated: you even could write
a[0] = randomBetween('a', 'f'); Just a little bit more readable ;-)
how to write the first 4 letters "long" in one line rather that for each line in an array?
There is no way, instead you could copy the elements in a loop or using a function like memcpy, strcpy. Taking your question wordly:
a[0] = 'l'; a[1] = 'o'; a[2] = 'n'; a[3] = 'g';
But this is not what you want, I guess :-) See also the strcpy-example below.
How to combine 2 strings?
Again, either using a loop or the functions mentioned above:
char *first = "Hello ";
char *second = "World";
char combined[12];
int currentIndex = 0, i = 0;
// copy characters from "first" as long we did not find a \0
while(first[i] != 0)
combined[currentIndex++] = first[i++];
i = 0;
// copy characters from "second" as long we did not find a \0
while(second[i] != 0)
combined[currentIndex++] = second[i++];
// finally don't forget to null-terminate!
combined[currentIndex] = 0;
Using e.g. strcpy is much easier ;-)
char *first = "Hello ";
char *second = "World";
char combined[12];
strcpy(combined, first);
strcpy(&combined[6], second);
What are we doing here? The first strcpy-call copies simply "first" to "combined". But the second calls seems to be interesting. There we copy "second" to the 7th position (start counting from 0, therefor 6). At this position was the \0-character after the first function call. But we don't want the string to end here, so we override it with the first character of the second string. One nice thing is that strcpy automatically copies the terminating \0 at the end. Quite simple, isn't it?
I have an integer say 002345 I want it to be split into Hours=00 Mins=23 Sec=45.I tried using "/" and "%" formula methods but it didn't work out since the first two terms are 00 is there any other way.can any one of you present me with a code.
thank you
Since you are not asking for conventional method of using "/" and "%".
Then you could convert the integer time to string and strip out hour, min, sec.
But storing time as simple integer is NOT a good idea, you would miss the leading zeros for hours. Hence its better to use a char array for this.
#include <stdio.h>
#include <string.h>
int main()
{
char hour[3]={0};
char min[3]={0};
char sec[3]={0};
int time = 2345;
char timeStr[10] = {0};
sprintf(timeStr, "%06d", time);
memcpy(hour, timeStr, 2);
memcpy(min, timeStr+2,2);
memcpy(sec, timeStr+4,2);
printf("%s:%s:%s",hour,min,sec);
}
Way i recommend is:-
#include <stdio.h>
#include <string.h>
int main()
{
char hour[3]={0};
char min[3]={0};
char sec[3]={0};
char timeStr[] = "002345";
memcpy(hour, timeStr, 2);
memcpy(min, timeStr+2,2);
memcpy(sec, timeStr+4,2);
printf("%s:%s:%s",hour,min,sec);
}
Then convert hour,min, sec to integer using atoi();
Assuming your integer is 2345 (since leading zeroes are irrelevant), you can just use:
hh = val / 10000;
mm = (val / 100) % 100;
ss = val % 100;
If instead you have a string (it's unclear because your tags indicate this but there's no mention of it in the question body), you simply call something like atoi or strtol on each two-character segment.
I'm writing a function that should parse a string containing a description of a dice roll, for instance "2*1d8+2". I extract the four values OK when they are integers, but I want to be able to use floats as well for the multiplier and the addition at the end. Things get nasty when I try to parse such a string: "1.8*1d8+2.5".
I have determined that the problem is with the function strcspn. I ask it to parse the input string s (which contains the dice string) and stop at either an asterisk or an 'x':
const char * s = "1.8*1d8+2.5";
size_t l = strcspn(s,"*x");
The function should return 3, as the asterisk is at the 4th position. However, it seems to stop on the decimal separator (period) and returns 1.
It's not that I can't continue writing my function without this, as there are other ways to get things done, but still I'm curious why such a thing would happen. Has anyone ever encountered this problem before?
[EDIT]
Nevermind, I've found the answer, and it was my stupidity rather than the compiler playing tricks on me. I used this code:
if (l = strcspn(s,"*x") < strlen(s)) {
...
which returned 1 (or true) because strcspn(s,"*x") < strlen(s) evaluates to true - and was assigned to the l variable. I should have added parentheses:
if ((l = strcspn(s,"*x")) < strlen(s)) {
...
Thanks for your answers nonetheless, particularly #sleske, who made me analyse my code more deeply (which led to finding the answer).
There must be an error somewhere else. I wrote a test program:
#include <stdio.h>
#include <string.h>
void main(){
const char * s = "1.8*1d8+2.5";
size_t l = strcspn(s,"*x");
printf("l: %d\n", l);
}
and compiled it with gcc on Linux. On my system, it outputs "3".
Please post a complete, working example that exhibits the problem. Then we'll see...
Your code works just as you posted it for me1.
#include <stdio.h>
#include <string.h>
int main(void) {
const char * s = "1.8*1d8+2.5";
size_t l = strcspn(s,"*x");
printf("%zd (%.*s)\n", l, (int)l, s);
return 0;
}
so ross$ ./a.out
3 (1.8)
1. Mac OS X 10.6.4
I'd use sscanf instead of manually finding stop points and parsing myself. You can get your integers and floats easily out of the string with that.
This code:
#include <stdio.h>
#include <string.h>
int main(void)
{
const char * s = "1.8*1d8+2.5";
size_t l = strcspn(s,"*x");
printf("<<%s>> %zd <<%s>>\n", s, l, s+l);
return 0;
}
produces this answer on MacOS 10.6.4 (GCC 4.5.1):
<<1.8*1d8+2.5>> 3 <<*1d8+2.5>>
If your compiler and library does not produce the same answer, get a fixed/upgraded version of the software.
(NB: The 'z' modifier in the printf() format string is a C99 feature - it indicates that the type of the parameter is size_t.)