Related
I'm trying to write a function in C, that removes the second array's elements from the first array if the first array fully contains the second array in the exact same order.
I know it's complicated to ask in words, so here are some examples:
If Array-1 is hello and Array-2 is lo, then the output should be hel.
If Array-1 is hello hello and Array-2 is lo, then the output should be hel hel.
If Array-1 is hello and Array-2 is call (the first array does not contain all of the second array), then the output should be hello. (It shouldn't be changed.)
I wrote some code but when I try 2nd example (the hello hello one), it gives me hello hel, not hel hel.
char removeText (char a[], char b[], int lengthA, int lengthB) {
int indexB = 0, i=0;
char d[lengthA];
for (; i<lengthA; i++) {
if (a[i]==b[indexB]) {
indexB++;
if (indexB==lengthB) {
for (int k=0, j=0; k<i-lengthB; j++, k++) {
d[k] = a[j];
}
}
}
else {
i -= indexB;
indexB = 0;
}
}
printf("%s", d);
if(indexB!=lengthB) {
return *a;
}
return *d;
}
int main(void) {
char a[] = "hello hello";
char b[] = "lo";
int c = 11;
int d = 2;
removeText(a, b, c, d);
return 0;
}
The output should be given with return. The printf("%s", d); part is just for trying if the code works or not.
I know what's wrong in my code. The
if (indexB==lengthB) {
for (int k=0, j=0; k<i-lengthB; j++, k++) {
d[k] = a[j];
}
}
part causes the error but how can I fix it?
Your problem is in the lines:
for (int k=0, j=0; k<i-lengthB; j++, k++) {
d[k] = a[j];
}
Each time you find a pattern in a, you copy all a data into d, cancelling what have been done before.
To highlight this, you should modify your code with some debug info:
printf("copy to d from a, indexd for %d to %d\n", 0, i-lengthB)
for (int k=0, j=0; k<i-lengthB; j++, k++) {
d[k] = a[j];
}
You could have noticed too that k and j are always equal.
One more question, how do you code if the pattern to remove is not at the end of input, or is not present in input ? Try it.
To solve your problem, I would advice a different approach: have a counter for ignored character in a and copy the character when pattern is not found, something like:
char * removeText (char a[], char b[], int lengthA, int lengthB) {
int indexB = 0, i=0;
int ignored = 0;
char d[lengthA] = "";
for (; i+ignored<lengthA; i++) {
if (a[i+ignored]==b[indexB]) {
indexB++;
if (indexB==lengthB) {
ignored += lengthB;
printf("ignored = %d\n", ignored);
}
}
else {
i -= indexB;
indexB = 0;
printf("d[%d] = a[%d] (%c)\n", i, i+ignored , a[i+ignored ]);
d[i] = a[i+ignored];
}
}
printf("%s", d);
strcpy(a, d);
return a;
}
I have an algorithm that search for a exit of a maze using recursive function , how i pass this to a function without recursive but using stack?What this algorithm do is basically , try to found the exit of a matriz , if the next step is 0 or if has already been covered comeback and try another path, but a i need to change the recursive function to a function using stack instead of recursion how i do that?
void print_maze(char **maze, int width, int height) {
for (int i=0; i<13; i++ ){
for (int j=0; j<10; j++ )
{
printf ("%d", maze[i][j]);
}
printf("\n");
}
}
int maze(int x_current, int y_current,char **mazeHere, int height,int width)
{
if (x_current < 0 || x_current >= width || y_current < 0 || y_current >= height)
return 0;
char here = mazeHere[x_current][y_current];
if (here == 3)
return 1;
if(here == 0 || here == 2)
return 0;
mazeHere[x_current][y_current] = 2;
if(maze(x_current ,y_current-1,mazeHere,height,width))return 1;
if(maze(x_current+1,y_current,mazeHere,height,width))return 1;
if(maze(x_current,y_current+1,mazeHere,height,width))return 1;
if(maze(x_current-1,y_current,mazeHere,height,width))return 1;
else{ mazeHere[x_current][y_current] = 1;
return 0;
}
}
int main(void)
{
char matriz [13][10]={
{0,0,0,0,0,0,0,0,0,0},
{0,0,1,1,1,1,1,0,0,0},
{0,0,1,0,0,0,1,0,0,0},
{0,0,1,0,0,0,1,0,0,0},
{1,1,1,0,1,1,1,1,1,0},
{0,1,0,0,1,0,0,0,0,0},
{0,1,1,0,1,1,1,0,0,0},
{0,0,1,0,1,0,0,0,1,0},
{0,0,1,0,0,0,1,1,1,0},
{0,0,1,1,1,1,1,0,0,0},
{0,0,0,0,0,0,1,0,0,0},
{0,0,0,0,0,0,1,1,1,3},
{0,0,0,0,0,0,0,0,0,0},};
int b= 0;
int height = 10;
int width = 13;
int p = 0;
int o = 0;
char **a = malloc(width * sizeof(char*));
for(int x = 0; x< width; x++){
a[x] = malloc(height * sizeof(char));
}
for (int i=0; i<13; i++ ){
for (int j=0; j<10; j++ )
{
a[i][j]= matriz[i][j];
}
}
int res = maze(4,0,a,height,width);
puts(res ? "success!" : "no luck!");
print_maze(a, width, height);
return 0;
}
I understand it's hard without recursion. By the way, conversion from recursion into using stack is not so hard, if you wrote code of stack data structure and its operation. We are going to pursue the matter on the assume.
Recursive function basically has structure like this:
position *seek(position *now, type arg...){
...
if(condition){
return NULL;
} else {
now->next = seek(arg_next);
}
}
It's OK to understand just with your feeling. What it does here is chaining new result to results until now. In other words, storing results as data structure. Here, data structure changes to stack. Then...:
void seek(stack *stack, type arg...){
...
while(1){
if(condition){
break;
} else {
stack->push(next_result)
}
}
}
It's so easy! All that is left is increasing conditions and considering backtracking. Based on the above, try to rewrite your code!
I want to delete multiple elements from array using index array,this is my code:
// b is an index array, n is size of b,
// player is the array need to be delete elements,
// size is the size of player
void play_cards(int b[],int n,int player[],int *size){
int i;
for(i = 0; i < n; i++)
delete_cards(b[i],player,size);
}
void delete_cards(int n,int player[],int *size){
int i;
for(i = n; i < *size; i++)
player[i] = player[i+1];
*size -= 1;
}
int main(void){
int player[10] = {1,2,3,3,4,4,5,5,6,7};
int index[6] = {2,3,4,5,6,7};
int size = 10;
play_cards(index,6,player,&size);
for(int i = 0; i < size; i++)
printf("%d|",player[i]);
puts("");
return 0;
}
I expect print the player should be 1,2,6,7 instead of 1,2,3,4. How should I fix it?
First I would not call the function delete_cards as it suggests that it deletes multiple cards which it does not - just delete_card would make things more clear.
Anyway - when you change the player array before you have played all cards in the index array, you change the meaning of the indexes. This is why your current code doesn't work.
So you can do two things:
a) Play all cards first and then delete the cards played. This could be done by first marking played card with -1 and then have a loop where you removed all element being -1
or
b) Play a card, delete it and adjust the remaining elements in index by decrementing them by one. Note: This solution requires that index is sorted (lowest first).
Solution a) could look something like this:
void delete_played_cards(int player[],int *size)
{
int i;
int next_pos = 0;
int deleted = 0;
for(i = 0; i < *size; i++)
{
if (player[i] != -1)
{
player[next_pos] = player[i];
if (i != next_pos)
{
player[i] = -1;
}
++next_pos;
}
else
{
++deleted;
}
}
*size -= deleted;
}
void play_cards(int b[],int n,int player[],int *size)
{
int i;
for(i = 0; i < n; i++)
{
player[b[i]] = -1; // Mark card as played
}
delete_played_cards(player,size);
}
int main(void)
{
int player[10] = {1,2,3,3,4,4,5,5,6,7};
int index[6] = {2,3,4,5,6,7};
int size = 10;
play_cards(index,6,player,&size);
for(int i = 0; i < size; i++)
printf("%d|",player[i]);
puts("");
return 0;
}
Modify play_cards:
void play_cards(int b[], int n, int player[], int *size)
{
int i;
for(i = n-1; i >= 0; i--)
delete_cards(b[i],player,size);
}
This will start deleting from the end of array.
As BLUEPIXY mentioned.
here is a pseudocode that you can work with:
given a sorted list, 1..n
for i = 2 up to length of list:
if list[i] is equal to list[i-1]:
shift the sublist [2..] 1 position to the left
else
increment i by 1
If you want to delete easily and efficiently without using loop you can use memcpy
#include <stdio.h>
#include <string.h>
#define INDEX_MAX 6
int main ()
{
int size = 10;
int src[] = {1,2,3,3,4,4,5,5,6,7};
int index[] = {2,3,4,5,6,7};
int x;
size = size - INDEX_MAX;
memcpy(src+2, src+8, sizeof(int)*(size-2));// - 2 since index 1 and 2 remains in the array
for(x = 0; x < size; x++){
printf("%d",src[x]);
}
return(0);
}
this is my first post here and I'm very new to C.
I want to write a program that is able to print matrixes. It should look like:
----
-o--
ooo-
----
So i want that to be printed for the beginning.
My current code is:
// 4. Exercise
// Learn 2d arrays
#include <stdio.h>
char z;
char s;
char m1_ptr;
void createMatrix()
{
for(z = 0; z != 4; z++)
{
for (s = 0; s != 4; s++)
{
printf("%c", *m1_ptr);
}
printf("\n");
}
}
//------------------------------------------------------------------
int main()
{
char o = o;
char c = '-';
// And some variables for the matrix count:
char matrix_1 [4][4] ={{c,c,c,c},{c,o,c,c},{o,o,o,c},{c,c,c,c}};
char *m1_ptr = &matrix_1 [z][s];
createMatrix(matrix_1 [0][0]);
/* for(z = 0; z != 4; z++)
{
for (s = 0; s != 4; s++)
{
printf("%c", matrix_1 [z][s]);
}
printf("\n");
}
*/
return 0;
}
It works if I put the void function into the main, but since there are much more matrixes coming I want to do that in an extra function to make it more readable.
If I compile that I get the error message:
"Line17: Error: invalid type argument of unary '*' ('have int')"
(edit: line 17 is where it says "printf("c......")
I looked at other questions, but since I only understand super simple programs yet that didn't work out for me.
Does anyone know how that could be fixed?
(It would be nice if the answer explains why, since I have very little experience with pointers)
I think your looking for something like this:
#include <stdio.h>
#define ROW 4
#define COLUMN 4
void printMatrix(int rowLength, int columnLength, char matrix[rowLength][columnLength]) {
int rowCount, columnCount;
for(rowCount = 0; rowCount < rowLength; rowCount++) {
for(columnCount = 0; columnCount < columnLength; columnCount++)
printf("%c", matrix[rowCount][columnCount]);
printf("\n");
}
}
int main() {
char o = 'o';
char c = '-';
char matrix_1 [ROW][COLUMN] = {
{c,c,c,c},
{c,o,c,c},
{o,o,o,c},
{c,c,c,c}
};
printMatrix(ROW, COLUMN, matrix_1);
return 0;
}
It prints the pattern you want
#include <stdio.h>
void displayMatrix( char pMatrix[rCount][cCount], int rCount, int cCount )
{
for(int i = 0; i < rCount; i++ ) // one loop for each row
{
for (int j = 0; j < cCount; j++) // one loop for each column
{
printf("%c", pMatrix[i][j]);
}
printf("\n"); // prep for next row
}
}
//------------------------------------------------------------------
static const o = 'o';
static const c = '-';
int main()
{
// And some variables for the matrix count:
char matrix_1 [][] ={{c,c,c,c},{c,o,c,c},{o,o,o,c},{c,c,c,c}};
displayMatrix(matrix_1,
sizeof( matrix_1) / sizeof(matrix_1[0]), // = number of rows
sizeof( matrix_1[0]) ); // = number of columns
return 0;
}
I need to create a program which would ask from user to input a string and then function in program needs to separate it to 2 strings of same size (user always inputs even number of chars) and after that it has to "shuffle" them...
So it should basically do this:
user inputs: A1B1C1D1
code should make 2 same sized strings: A1B1 and C1D1 and after that it should "shuffle" them to look like this: A1C1B1D1.
So it needs to take first 2 elements of first string, then first 2 elements of second string and so on…
My problem is that when I input A1B1C1D1, after I run the program, I get AC1BD1 (it leaves out 2nd char from first array).
#include<stdio.h>
#include<string.h>
#define N 100
void shuffle(char *cards) {
int i, n, x=0, c1=0, c2=0, j=0;
char tmp1[N]={0}, tmp2[N]={0};
n=strlen(cards);
//divide to 2 arrays with same number of elements
for(i=0; i<n; i++){
if(i<(n/2)){
tmp1[i]=cards[i];}
else{
tmp2[x]=cards[i];
x++;
}
}
//storing 2 elements from first array, then 2 elements from second array and so on
for(i=0; i<n; i++){
if(j>3){
j=0;
}
if(j<=1){ // store 2 elements from 1st array
cards[i]=tmp1[c1];
c1++;
j++;
}
if(j>=2){ // store 2 elements from 2nd array
cards[i]=tmp2[c2];
c2++;
j++;
}
}
printf("1st half:%s\n2nd half:%s", tmp1, tmp2);
printf("\n\t%s",cards);
return;
}
int main() {
char cards[N];
scanf("%s", cards);
shuffle(cards);
return 0;
}
The problem is here
if(j<=1){ // store 2 elements from 1st array
cards[i]=tmp1[c1];
c1++;
j++;
}
if(j>=2){ // store 2 elements from 2nd array
cards[i]=tmp2[c2];
c2++;
j++;
}
Make the second if as an "else if" (just an "else" is also enough)
What happens is that after you increment j from 1 to 2, you go into the second if statement, and rewrite on the same index on cards.
If you don't mind an alternative suggestion for "shuffling your deck of cards" in a much simpler way:
void shuffle(char *cards)
{
char tmp[N]={0};
int n = strlen(cards);
for (int i=0; i<n/2; i++)
tmp[i*2+0] = cards[i];
for (int i=0; i<n/2; i++)
tmp[i*2+1] = cards[i+n/2];
for (int i=0; i<n; i++)
cards[i] = tmp[i];
}
You call it shuffle and cards.
Wouldnt it be better to make a card structure that has two elements?
I thinky your j in the for loop is behaving wrong.
I will double check this and edit this answer if it wasnt j.
EDIT:
Your cradcount was off by a bit and you wrote the wrong index.
Here is some working code:
j = 0;
i = 0;
while(i<n)
{
++j;
if(j == 1 || j == 2)
{ // store 2 elements from 1st array
cards[i++]=tmp1[c1++];
}
else if(j == 3 || j == 4)
{ // store 2 elements from 2nd array
cards[i++]=tmp2[c2++];
}
else
{
j = 0;
}
}
In general you can use the debugger to see whats happening with your index. I assume this is homework and you have to write "optimal code". In general it would be beneficial to use varaiblaenames with more meaning.
EDIT2:
There is a nice solution below that illustrates time optimized code.
I wanted to add some code that i think is easier to read and maintain.
#include<stdio.h>
#include<string.h>
#define DECK_MAX 100
typedef struct
{
char group;
int number;
}Tcard;
typedef struct
{
Tcard card[DECK_MAX];
int count;
}Tdeck;
int ReadDeck(Tdeck * deck, const char *cardstring);
int DeckAddCopy(Tdeck * deck, Tcard * card);
int PrintDeck(Tdeck * deck, const char *deckname);
int InterleaveDecksCopy(Tdeck * target, Tdeck * source[], int sourcecount);
int SplitDeckCopy(Tdeck * source, Tdeck * target[], int targetcount);
int main() {
int e = 0;
char cardstring[100];
Tdeck deck, stackA, stackB, interleaved;
Tdeck * stacks[] = {&stackA, &stackB};
printf("Please input a cardstring: ");
scanf("%s", cardstring);
e |= ReadDeck(&deck, cardstring);
e |= PrintDeck(&deck, "cardstring");
e |= SplitDeckCopy(&deck, stacks, sizeof(stacks) / sizeof(Tdeck*) );
e |= PrintDeck(&stackA, "1st half");
e |= PrintDeck(&stackB, "2nd half");
e |= InterleaveDecksCopy(&interleaved, stacks, sizeof(stacks) / sizeof(Tdeck*) );
e |= PrintDeck(&interleaved, "interleaved");
if( e != 0) printf("There was an error dureing execution.\n");
return e;
}
int ReadDeck(Tdeck * deck, const char *cardstring)
{
int e = 0;
int varCount, n, total = 0;
Tcard card;
memset(deck, 0, sizeof(Tdeck));
do{
n = 0;
varCount = sscanf(&cardstring[total], "%c%i%n", &card.group, &card.number, &n);
total += n;
if( varCount == 2 )
{
//check if card is valid?
e |= DeckAddCopy(deck, &card);
}
else
{
if(strlen(cardstring) != total)
{
//string was not read completely
e |= 1;
}
}
}while(varCount == 2);
return e;
}
int DeckAddCopy(Tdeck * deck, Tcard * card)
{
int e = 0;
if(deck->count >= DECK_MAX)
{
e |= 1;
}
else
{
memcpy(&deck->card[deck->count++], card, sizeof(Tcard));
}
return e;
}
int PrintDeck(Tdeck * deck, const char *deckname)
{
int c;
printf("%s contains %i cards%s", deckname, deck->count, (deck->count == 0)? ".\n":": ");
for(c = 0; c < deck->count; ++c)
{
printf("%c%i%s", deck->card[c].group, deck->card[c].number, ( c+1 < deck->count) ? ", ":".\n");
}
return 0;
}
int InterleaveDecksCopy(Tdeck * target, Tdeck * source[], int sourcecount)
{
int c, s, e = 0;
memset(target, 0, sizeof(Tdeck));
for(c = 0; c < DECK_MAX; ++c)
{
for(s = 0; s < sourcecount ; ++s)
{
if(c < source[s]->count)
{
e |= DeckAddCopy(target, &source[s]->card[c]);
}
}
}
return e;
}
int SplitDeckCopy(Tdeck * source, Tdeck * target[], int targetcount)
{
int c, t, e = 0;
for(t = 0; t < targetcount ; ++t)
{
memset(target[t], 0, sizeof(Tdeck));
}
c = 0;
for(t = 0; t < targetcount ; ++t)
{
int cMax = (source->count) - (((source->count)/targetcount) * targetcount - t - 1 );
for( ; c < (t+1)*(source->count)/targetcount ; ++c)
{
e |= DeckAddCopy(target[t], &source->card[c]);
}
}
return e;
}