I want to generate random names to book.author and book.title
but when i print nothing shows.
typedef struct Book{
char title[20];
char author[20];
int pages;
double price;
}Book;
int randInit(int min, int max){
return min + rand()%(max -min +1);
}
void rand_Init_Book(Book *b){
int len =randInit(10,20);
for(int i =1 ; i < 1;i++)
{
b->title[i] = (char)randInit('a','z');
}
len =randInit(10,20);
for(int i =1 ; i < randInit(10,20);i++)
{
b->author[i] = randInit('a','z');
}
b->pages = randInit(5,2000);
b->price = (100 + rand()%(10000-100))/100.;
}
The names will not be actual names, just some string. When I exit the loop and i want to print it says that the string is empty. I've tried with strcpy whit another string but the same result.
No iteration
for(int i =1 ; i < 1;i++) never iterates as i < 1 is immediately false.
Code fails to index properly
Array's are zero-based indexed.
// for(int i =1 ; i < randInit(10,20);i++)
for(int i = 1; i < randInit(10,20); i++)
Excessive length
char author[20]; can hold a string up to 19 characters + the final null character.
// len =randInit(10,20);
len = randInit(10, 20 - 1);
No need to repeatedly find a random length
// for(int i =1 ; i < randInit(10,20);i++)
for(int i = 0; i < len;i++)
Missing null character
A string needs a final null character.
Tips
Improve formatting - use an auto formatter.
Avoid naked magic numbers like 10.
Example:
#define NAME_LENGTH_MIN 10
void rand_Init_Book(Book *b) {
int len = randInit(NAME_LENGTH_MIN, sizeof b->title - 1);
for (int i = 0; i < len; i++) {
b->title[i] = (char) randInit('a', 'z');
}
b->title[len] = '\0';
len = randInit(NAME_LENGTH_MIN, sizeof b->author - 1);
for (int i = 0; i < len; i++) {
b->author[i] = (char) randInit('a', 'z');
}
b->author[len] = '\0';
b->pages = randInit(5, 2000);
b->price = (100 + rand() % (10000 - 100)) / 100.0;
}
Related
I have to make a program that sort strings (with exact length 7 chars) by using radix sort. I already made a function that sort each column separately. My problem is how to make the whole string move, not just one char. It's really problematic for me to see how should it work in C.
I made one array "char strings[3][8]" and "char output[3][8]" to get sorted 3 strings with exact 7 chars in each one. For example sorting these strings:
strcpy(strings[0], "kupbars");
strcpy(strings[1], "daparba");
strcpy(strings[2], "jykaxaw");
In output I get:
dakaaaa
juparbs
kypbxrw
Each column is sorted correctly but chars don't stick together. I tried many ways for 3 hours but nothing works.
My code looks like this:
void countingSort(char a[][8], char b[][8]) {
int c[123];
for (int pos = 6; pos >= 0; pos--) {
for (int i = 0; i < 123; i++)
c[i] = 0;
for (int i = 0; i < 3; i++)
c[(int)a[i][pos]]++;
for (int i = 1; i < 123; i++)
c[i] += c[i - 1];
for (int i = 2; i >= 0; i--) {
b[--c[(int)a[i][pos]]][pos] = a[i][pos];
}
}
}
(There are constants limiting string length etc. because it's easy to change it to variable - I just focused on getting this program work properly.)
Try changing the loop to move an entire string:
for (int i = 2; i >= 0; i--) {
int k = --c[(int)a[i][pos]];
for(int j = 0; j < 8; j++) {
b[k][j] = a[i][j];
}
}
You could do a circular list but it's a little overhead. I propose you to use memmove().
#include <string.h>
void array_move_forward(char array[3][8]) {
for (int i = 0; i < 3; i++) {
char tmp = array[i][6];
memmove(array[i] + 1, array[i], 6);
array[i][0] = tmp;
}
}
void array_move_rewind(char array[3][8]) {
for (int i = 0; i < 3; i++) {
char tmp = array[i][0];
memmove(array[i], array[i] + 1, 6);
array[i][6] = tmp;
}
}
A other solution would be to manipulate your string yourself and using a index, that indicate the first letter of your string.
{
char str[7];
int i = 0;
...
int j = i;
for (int k = 0; k < 7; k++) {
char tmp = str[j++ % 7];
}
}
With that you could rotate your string just with i++ or i--.
struct my_string_radix {
char str[7];
int begin;
}
I have an array called puzzle which consist of words/letters/random strings and I want to check if it has any of the same strings in another array called dictionary (the strings in dictionary are listed in alphabetical order)
So I believe my problem is the binary search in my program, I'm not entire sure how to work around it using strings. I tried to use some strcmp() but I don't think thats the way to go?
When the program runs, it gets no output. that there is no matches but there are.
here is my binary search function:
int binsearch(char **dictionary, char *puzzle) {
int start = 1; //excluded first string of dictionary array bc #
int end = listlength;
while (start < end) {
int mid = (start + end) / 2;
int temp = strcmp(dictionary[mid], puzzle);
if (temp < 0) {
start = mid + 1; //it is in upper half
} else
if (temp > 0) { //check lower half
end = mid;
} else
return 1; //found a match hopefully
}
return 0;
}
and my entire code is here if maybe something you need to see
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define listlength 149256
#define maxWordLen 19
char **getWords(int rows, int cols);
void freeArray(char **array, int rows);
char **makeGridArray(int rows, int cols);
int binsearch(char **dictionary, char *puzzle);
void wordSearch(char **dictionary, char **puzzle, int row, int col);
const int DX_SIZE = 8;
const int DX[] = { -1, -1, -1, 0, 0, 1, 1, 1 };
const int DY[] = { -1, 0, 1, -1, 1, -1, 0, 1 };
int main() {
//read in dictionary
int i, j, x = 0, numCases, gridRow, gridCol;
char **words = getWords(listlength, maxWordLen);
//Get number of cases.
printf("enter number of cases:\n");
scanf("%d", &numCases);
//process each case.
while (x < numCases) {
scanf("%d%d", &gridRow, &gridCol);
//make word search grid
char **grid = makeGridArray(gridRow + 1, gridCol);
/* for testing if grid is storing properly
for (i = 0; i < gridRow + 1; i++) {
printf("%s\n", grid[i]);
}
*/
printf("Words Found Grid #%d:\n", x + 1);
wordSearch(words, grid, gridRow + 1, gridCol);
x++;
freeArray(grid, gridRow + 1);
}
freeArray(words, listlength);
}
char **getWords(int rows, int cols) {
int i;
//allocate top level of pointers.
char **words = malloc(sizeof(char*) * rows);
//allocate each individual array
for (i = 0; i < rows; i++) {
words[i] = malloc(sizeof(char) * cols + 1);
}
//read dictionary.txt
FILE *dictionary = fopen("dictionary.txt", "r");
for (i = 0; i < rows; i++) {
fgets(words[i], cols + 1,dictionary);
}
fclose(dictionary);
return words;
}
char **makeGridArray(int rows, int cols) {
//allocate top level of pointers.
char **grid = malloc(sizeof(char*) * rows);
int i, j;
//allocate each individual array
for (i = 0; i < rows; i++) {
grid[i] = malloc(sizeof(char) * cols + 1);
}
//read in user input grid
for (i = 0; i < rows; i++) {
gets(grid[i]);
}
return grid;
}
int binsearch(char **dictionary, char *puzzle) {
int start = 1; //excluded first string of dictionary array bc #
int end = listlength;
while (start < end) {
int mid = (start + end) / 2;
int temp = strcmp(dictionary[mid], puzzle);
if (temp < 0) {
start = mid + 1; //it is in upper half
} else
if (temp > 0) { //check lower half
end = mid;
} else
return 1; //found a match hopefully
}
return 0;
}
void wordSearch(char **dictionary, char **puzzle, int row, int col) {
int i, X, Y, dir;
char wordsfound[19] = { '\0' };
for (X = 0; X < row + 1; X++) {
for (Y = 0; Y < col; Y++) {
for (dir = 0; dir < DX_SIZE; dir++) //check every direction
for (i = 0; i < 19; i++) {
//will continue in direction DX,DY starting at x,y
int nextX = X + DX[dir] * i;
int nextY = Y + DY[dir] * i;
if (nextX < 0 || nextX >= row) break; //keep in bounds
if (nextY < 0 || nextY >= col) break;
//store the string of letters to check
wordsfound[i] = (puzzle[nextX][nextY]);
if (i > 3) { //minimum word is 4
wordsfound[i + 1] = '\0';
//if the string of letters is actually a word, print
int bin = binsearch(dictionary, wordsfound);
if (bin) {
printf("%s\n", wordsfound);
}
}
}
}
}
return;
}
void freeArray(char **array, int rows) {
//free arrays
int i;
for (i = 0; i < rows; i++) {
free(array[i]);
}
free(array);
}
The problem is in the getwords() function: you read the words from the dictionary with fgets() but forget to remove the trailing \n. All words in the dictionary have a trailing \n, so none of them match your searches.
Here is a corrected version:
char **getWords(int rows, int cols) {
char line[256];
int i;
//allocate top level of pointers.
char **words = malloc(sizeof(char*) * rows);
//read dictionary.txt
FILE *dictionary = fopen("dictionary.txt", "r");
for (i = 0; i < rows; i++) {
if (!fgets(line, sizeof line, dictionary))
line[0] = '\0';
line[strcspn(line, "\n")] = '\0';
words[i] = strdup(line);
}
fclose(dictionary);
return words;
}
Note that it would be better not to rely on a known magical listlength. You could also ignore comment and empty lines while reading the dictionary.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I am trying to code the Waterman algorithm in C.
Now when the length of the sequence exceeds 35 the program just lags.
I have no idea where to start looking, tried but got nothing worked out.
Here's the code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// Max Function Prototype.
int maxfunction(int, int);
// Prototype of the random Sequences generator Function.
void gen_random(char *, const int);
int main(int argc, char *argv[]) {
// Looping variable and Sequences.
int i = 0, j = 0, k = 0;
char *X, *Y;
int length1, length2;
// Time Variables.
time_t beginning_time, end_time;
// Getting lengths of sequences
printf("Please provide the length of the first Sequence\n");
scanf("%d", &length1);
printf("Please provide the length of the second Sequence\n");
scanf("%d", &length2);
X = (char*)malloc(sizeof(char) * length1);
Y = (char*)malloc(sizeof(char) * length2);
int m = length1 + 1;
int n = length2 + 1;
int L[m][n];
int backtracking[m + n];
gen_random(X, length1);
gen_random(Y, length2);
printf("First Sequence\n");
for (i = 0; i < length1; i++) {
printf("%c\n", X[i]);
}
printf("\nSecond Sequence\n");
for (i = 0; i < length2; i++) {
printf("%c\n", Y[i]);
}
// Time calculation beginning.
beginning_time = clock();
// Main Part--Core of the algorithm.
for (i = 0; i <= m; i++) {
for (j = 0; j <= n; j++) {
if (i == 0 || j == 0) {
L[i][j] = 0;
} else
if (X[i-1] == Y[j-1]) {
L[i][j] = L[i-1][j-1] + 1;
backtracking[i] = L[i-1][j-1];
} else {
L[i][j] = maxfunction(L[i-1][j], L[i][j-1]);
backtracking[i] = maxfunction(L[i-1][j], L[i][j-1]);
}
}
}
// End time calculation.
end_time = clock();
for (i = 0; i < m; i++) {
printf(" ( ");
for (j = 0; j < n; j++) {
printf("%d ", L[i][j]);
}
printf(")\n");
}
// Printing out the result of backtracking.
printf("\n");
for (k = 0; k < m; k++) {
printf("%d\n", backtracking[k]);
}
printf("Consumed time: %lf", (double)(end_time - beginning_time));
return 0;
}
// Max Function.
int maxfunction(int a, int b) {
if (a > b) {
return a;
} else {
return b;
}
}
// Random Sequence Generator Function.
void gen_random(char *s, const int len) {
int i = 0;
static const char alphanum[] = "ACGT";
for (i = 0; i < len; ++i) {
s[i] = alphanum[rand() % (sizeof(alphanum) - 1)];
}
s[len] = 0;
}
Since you null terminate the sequence in gen_random with s[len] = 0;, you should allocate 1 more byte for each sequence:
X = malloc(sizeof(*X) * (length1 + 1));
Y = malloc(sizeof(*Y) * (length2 + 1));
But since you define variable length arrays for other variables, you might as well define these as:
char X[length1 + 1], Y[length2 + 1];
Yet something else is causing a crash on my laptop: your nested loops iterate from i = 0 to i <= m, and j = 0 to j <= n. That's one step too many, you index out of bounds into L.
Here is a corrected version:
for (i = 0; i < m; i++) {
for (j = 0; j < n; j++) {
The resulting code executes very quickly, its complexity is O(m*n) in both time and space, but m and n are reasonably small at 35. It runs in less than 50ms for 1000 x 1000.
Whether it implements Smith-Waterman's algorithm correctly is another question.
I have a function that returns all the combinations of letters possible in the alphabet with repetition in a word of length LENTH_MAX. The function returns these combinations in a 2D array call 'arr'.
Since calculating the total number of arrays is a pain because you need to calculate factorial numbers [ (n + r - 1)!/r!(n - 1)! ] I decided to increasingly reallocate memory for the arrays in 'arr' as needed.
I set a variable called capacity that determinetes the initial size of 'arr' and a constant called CAP_INCR that specifies the number of arrays for which memory will be reallocated in addition to the memory already assigned. The program compiles ok by if I set CAP_INCR to 1, so that each time a new combination is found new memory is allocated for that array, the program crushes with a Segmentation fault: 11 message, if I set CAP_INCR to 100 if finishes correctly but the output is wrong, the first combination 'a a a' is repeated twice and the last combination 'z z z' is mission.
I'd really appreciate some help. I'm a decent programer in other languages but I'm just starting with C.
The code is:
#include <stdio.h>
#include <stdlib.h>
const unsigned short LENGTH_MAX = 3;
const char alphabet[] = "abcdefghijklmnopqrstuvwxyz";
#define CAP_INCR 1 /* memory increases */
unsigned char* combinations(unsigned char n, unsigned char r)
{
// n length of alphabet
// r length of figures
unsigned int set_counter = 0; //counting generated sequences
unsigned char *vector = NULL; //where the current figure is stored
unsigned char *arrTemp = NULL; // Temporary pointer store
unsigned int capacity = 100; // count current size of arr
unsigned char *arr = (unsigned char *)malloc(capacity * r * sizeof(unsigned char)); // multidimentional array
vector = (unsigned char *)malloc(sizeof(unsigned char) * r);
if(vector == NULL || arr == NULL)
{
fprintf(stderr, "error: insufficient memory\n");
exit(EXIT_FAILURE);
}
//initialize: vector[0, ..., r - 1] are 0, ..., r - 1
for(int l = 0; l < r; l++) //for(int l = 0; l < r; l++) // no repetition
vector[l] = 0;
//generate all successors
while(1)
{
set_counter++;
// check is arr current capacity is enough
if(set_counter > capacity)
{ // We need more memory
capacity += CAP_INCR;
arrTemp = (unsigned char *)realloc(arr, capacity * r * sizeof(unsigned char));
if(!arrTemp)
{
printf("Unfortunately memory reallocation failed.\n");
free(arr);
arr = NULL;
exit(0);
}
arr = arrTemp;
}
for(int x = 0; x < r; x++) { // assign a new combination to arr
//printf("%c ", alphabet[vector[x]]);
*(arr + set_counter*r + x) = vector[x];
}
//printf("(%u)\n", set_counter);
int j; //index
//easy case, increase rightmost element
if(vector[r - 1] < n - 1)
{
vector[r - 1]++;
continue;
}
//find rightmost element to increase
for(j = r - 2; j >= 0; j--) {
if(vector[j] != n - 1) {
break;
}
}
//terminate if vector[0] == n - r
if(j < 0)
break;
//increase
vector[j]++;
//set right-hand elements
for(j += 1; j < r; j++)
vector[j] = vector[j - 1];
}
return arr;
}
int main() {
unsigned char* arr = combinations(sizeof(alphabet)-1, LENGTH_MAX);
int c=0;
for (int i = 0; i < 3276; i++) // 3276 is the total number of combinations
{
for (int j = 0; j < 3; j++)
{
printf("%c ", alphabet[*(arr + i*3 + j)]);
}
printf("count: %d\n",++c);
}
return 0;
}
This is an extension of the previously asked question: link. In a short, I am trying to convert a C program into Matlab and looking for your suggestion to improve the code as the code is not giving the correct output.
C program:
void prga(unsigned char S[], unsigned char out[], int len) {
int i=0,j=0,x,t;
unsigned char key;
for (x=0; x < len; ++x) {
i = (i + 1) % 256;
j = (j + S[i]) % 256;
t = S[i];
S[i] = S[j];
S[j] = t;
out[x] = S[(S[i] + S[j]) % 256];
}
}
Matlab program:
function [out, i, j, S]=rc4out(i, j, S)
%for x = 1:length(key) % It should not work here as no key mentioned
i = mod( (i+1), 256);
j = mod( j + S(i), 256);
t = S(i);
S(i) = S(j+1);
S(j+1) = t;
out = mod(S(S(i) + S(j+1), 256));
EDIT:
Try this it do the same think as the c function: The lengh of S should be >= 256 or you will exceed it as mod() could return such index. I suggest you to change 256 in the function with the lenght provided to solve this issue.
Here you don't need the key variable.
function out = prga(S, len)
i=0; j=0; x=[]; t=[];
for x=0:len-1
i = mod(i+1, 256);
j = mod(j+S(i+1), 256);
t = S(i+1);
S(i+1) = S(j+1);
S(j+1) = t;
out(x+1) = S(mod(S(i+1)+S(j+1), 256)+1);
end
end
Or you can use the key variable to controle the loop
function out = prga(S, key)
i=0; j=0; x=[]; t=[];
for x=0:length(key)-1
i = mod(i+1, 256);
j = mod(j+S(i+1), 256);
t = S(i+1);
S(i+1) = S(j+1);
S(j+1) = t;
out(x+1) = S(mod(S(i+1)+S(j+1), 256)+1);
end
end