K&R valid input for arrays & pointers in the swap function - c

I'm having trouble with the things I am and am not allowed to do with arrays and pointers in the following code:
#include <stdio.h>
#define MAX 1000
void swap (char *v[], int i, int j);
main() {
int i = 1, j = 2;
int count;
char *a = "Bill ", *b = "went ", *c = "to the ", *d = "grocery store.";
char *v[MAX];
v[0] = a;
v[1] = b;
v[2] = c;
v[3] = d;
printf("String before swapping elements at index %d and %d: \n",i,j);
for(count = 0; count < 4; ++count)
printf("%s",v[count]);
printf("\n");
swap(v,i,j);
printf("String after swapping elements at index %d and %d: \n",i,j);
for(count = 0; count < 4; ++count)
printf("%s",v[count]);
printf("\n");
system("Pause");
return 0;
}
void swap (char *v[], int i, int j)
{
char *temp;
temp = v[i];
v[i] = v[j];
v[j] = temp;
}
Two things come to mind:
Why can't I write v[] = {a,b,c,d} after declaring *v[MAX]? In fact, I did a quick test and even this isn't allowed:
char v[MAX];
v[] = {'w','o','r','d','s'};
whereas char v[] = {'w','o','r','d','s'}; is accepted. Why is that?
Second thing, how can I re-write the for loop without having to use a magic number (in this case 4)? I tried using strlen in various ways but I got an error each time. The best I could come up with is a somewhat clumsy solution of declaring char *k; and changing the loop condition to
for(count = 0, k = v; *(k-1); ++count, ++k)
printf("%s",v[count]);
Surely there must be a more elegant way to loop through the v array?

how can I re-write the for loop without having to use a magic number
(in this case 4)?
One way of doing this, is to add a special terminator value ( usually NULL) in the array that you are iterating, e.g.
char *v[] = { a, b, c, d, NULL };
for(count = 0; v[count] != NULL; ++count)
printf("%s",v[count]);

char *v[] = { a, b, c, d};
int size = sizeof(v)/sizeof(*v);//4

Related

attach second text array on given position

How can i attach one text array to another text array in c on a given position. For example from input user enters 2 arrays and one digit which is the position.
( _ is empty space )
first: hi my name is ,i learn c
second: Jacob_
pos: 14
result hi my name is jacob ,i learn c
here is my code
#include<stdio.h>
#include<string.h>
#include<ctype.h>
void attach(char *a,char *b,char*c,int pos){
int i,j;
for(i = 0; i < pos;i++){
*(c+i) = *(a+i);
}
int lenB = strlen(b);
for(i = pos+1;i < lenB;i++){
*(c+i) = *(b+i);
}
int lenRes = lenB+pos;
int lenA = strlen(a);
for(i = lenRes;i < lenA;i++){
*(c+i) = *(a+i);
}
puts(c);
}
int main()
{
char a[1000],b[1000],c[1000];
gets(a);
gets(b);
int pos;
scanf("%d",&pos);
attach(a,b,c,pos);
return 0;
}
Most of your logic for accessing the strings or doing the loops was just wrong. For example, your second for loop would have zero iterations whenever the user specifies a pos such that pos + 1 >= lenB, so that can't be right. You also forgot to add a null termination character at the end of the string.
I kept the basic structure of your program, but cleaned up some minor things and fixed the logic.
#include <stdio.h>
#include <string.h>
void attach(const char * a, const char * b, char * c, int pos) {
int i;
for (i = 0; i < pos; i++) {
c[i] = a[i];
}
int lenB = strlen(b);
for (i = 0; i < lenB; i++) { // I fixed this line
c[pos + i] = b[i]; // I fixed this line
}
int lenA = strlen(a);
for (i = pos; i < lenA; i++) { // I fixed this line
c[i + lenB] = a[i]; // I fixed this line
}
c[lenA + lenB] = 0; // I added this
}
int main()
{
char c[1000];
attach("Hi my name is , I learn C", "David", c, 14);
puts(c); // I moved this to a better place
}
This program produces the output "Hi, my name is David, I learn C".
By the way, c[i] is equivalent to *(c + i), so use whichever syntax you find more readable.
Also, to help you find better answers with Internet searches in the future, this operation is not usually called "attach". It is usually called "insert". And we don't call these things "text arrays", we call them "strings". So a better way to ask your question is: "How can I insert a string into the middle of another string?"

C - Get all permutations of a string and assign a number to every character that repeats

This has been a nightmare for me. I already managed to get the first part; get all permutations from a string thanks to this code (C language). It works!
#include <stdio.h>
#include <string.h>
/* Function to swap values at two pointers */
void swap(char *x, char *y)
{
char temp;
temp = *x;
*x = *y;
*y = temp;
}
/* Function to print permutations of string
This function takes three parameters:
1. String
2. Starting index of the string
3. Ending index of the string. */
void permute(char *a, int l, int r)
{
int i;
if (l == r)
printf("%s\n", a);
else
{
for (i = l; i <= r; i++)
{
swap((a+l), (a+i));
permute(a, l+1, r);
swap((a+l), (a+i)); //backtrack
}
}
}
/* Driver program to test above functions */
int main()
{
char str[] = "CASA";
int n = strlen(str);
permute(str, 0, n-1);
return 0;
}
Now, how can I do the second part? I already output the 24 different permutations.
What needs to be done is, assign a number to each character that repeats. I haven't found a way to do this in C so far.
For example, my output for the word "CASA" should be this. (it doesn't matter if the number is subscript or not by the way, I just want to identify which one is the first/second/third of the same character).
You can create an auxiliary data structure that represents your indexed letters, for example
struct tag {
char str[4];
};
Now, instead of permuting your string directly, you can create a tag for each letter and permute that:
void swap(struct tag *a, int i, int j)
{
struct tag temp = a[i]; a[i] = a[j]; a[j] = temp;
}
void do_permute(struct tag *tag, int lo, int hi)
{
if (lo == hi) {
for (int i = 0; i < hi; i++) {
if (i) printf(" ");
printf("%s", tag[i].str);
}
printf("\n");
} else {
for (int i = lo; i < hi; i++) {
swap(tag, lo, i);
do_permute(tag, lo + 1, hi);
swap(tag, lo, i);
}
}
}
This is more or less your original function, but I've taken the liberty of making the upper bound exclusive, as is usual in C. (I'm always a bit uneasy when I see <='s in for loop conditions.)
Of course, you must create the tags. You can do this in a front-end function to the back-end above. This function should also determine the length of the string. You can create your tags in two steps:
Keep a count of all individual characters. Assign an index to each letter.
In a second pass, remove the number from each letter that ocurs only once.
Now you're good to go:
void permute(const char *str)
{
int l = strlen(str);
struct tag *tag = malloc(l * sizeof(*tag));
int count[256] = {0};
// first pass: assign individual indices for each letter
for (int i = 0; i < l; i++) {
unsigned char k = str[i];
count[k]++;
snprintf(tag[i].str, sizeof(tag[i].str), "%c%d", str[i], count[k]);
}
// second pass: remove index for single instances
for (int i = 0; i < l; i++) {
unsigned char k = str[i];
if (count[k] == 1) tag[i].str[1] = '\0';
}
do_permute(tag, 0, l);
free(tag);
}
Now permute("CASA") will write a list of indexed permutations. (But note how you can pass a string literal – the string is not changed in any way while permuting.)
See everything put together in an example here.

Print Array in required order

Im a new programmer
I am have an char array M = "something",
and I want to print in this way
t
eth
methi
omethin
something
can any one help me in the logic to print in this way using loops.
I have used this code so far, but shows Segmentation error, can any body help me out where I have gone wrong.
main() {
int i, j, k, m, n;
char a[] = "Something";
n = sizeof(a) - 1;
for (i = 0; i < (n/2) + 1; i++) {
for (j = 0; j <= n - i; j++)
printf(" ");
for (m = (n/2) - i; !(m >= (n/2)); m--)
printf("%c",a[m]);
for (k = (n/2);k <= (n/2) + i; k++)
printf("%c", a[k]);
printf("\n");
}
}
Linear solution (note the string must be modifiable)
#include<stdio.h>
#include<string.h>
int main()
{
char array[] = "something";
char * str = array;
int size = strlen(str);
int i=size/2;
if(size%2==0)i--;
for(;i>=0;i--){
char c = str[size-i];
str[size-i]='\0';
printf("%s\n",str+i);
str[size-i]=c;
}
}
I remember i had a homework like this when I was learning c :)
Update:
As Jonathan Leffler pointed out, without modifying the string itself, we can print by passing the string length to printf function. (I didn't know the %.*s specifier :)) Well it shows we can learn even from a basic simple problems :) Thanks Jonathan. This makes the code more elegant and compact.
#include<stdio.h>
#include<string.h>
void print_string(const char *string)
{
int size = strlen(string),i;
for (i = (size - 1) / 2; i >= 0; i--)
printf("%d:%d: %.*s\n", i, size-2*i, size-2*i, string+i);
}
int main()
{
char * a = "something";
print_string(a);
}
C program i created , hope this helps.
#include<stdio.h>
int main()
{
char *str,*p1,*p2;
int count=0;
str="something";
p1=str; //points to the first element of the string.
while(*(str+1)!='\0')
str++;
p2=str; //points to the last element of the string.
while(*p1!='\0')
{
if(p1==p2)
printf("%c\n",*p1);
if(p1>p2)
{
while(p2<=p1)
{
printf("%c",*p2);
p2++;
count++;
}
p2=p2-(count);
count=0;
printf("\n");
}
p1++; // move to right.
p2--; // move to left.
}
}
Output :
Time complexity of this algorithm would be O(n^2)

Why this C programming can not run crrectly?

It's just a sample test that I want to unite the list Lb and La without repeat element. It didn't work, and returned -1073741510, I think maybe the array overflow, but I can't find where the problem is
This is my code:
#include <stdio.h>
void Union(char *La, char *Lb);
int ListLength(char *L);
void GetElem(char *L, int i, char *e);
int LocateElem(char *L, char *e, int (*comp)(char a, char b));
int compare(char a, char b);
void ListInsert(char *, int, char *);
int main(){
char *La;
char *Lb;
int i;
for(i = 0; i <= 10; ++i){
La[i] = i;
Lb[i] = i + 5;
}
La[i] = '\0';
Lb[i] = '\0';
Union(La, Lb);
for(i = 0; La[i] != '\0'; ++i){
printf("%c\n", La[i]);
}
return 0;
}
//unite La and Lb without repeat elements
void Union(char *La, char *Lb){
int La_length = ListLength(La);
int Lb_length = ListLength(Lb);
int i = 0;
char *e;
for(i; i<= Lb_length; ++i){
GetElem(Lb, i, e);
if(!LocateElem(La, e, compare))
ListInsert(La, ++La_length, e);
}
}
//caculate the length of L
int ListLength(char *L){
int i;
for(i = 0; *(L + i) != '\0'; ++i);
return i;
}
void GetElem(char *L, int i, char *e){
*e = *(L + i);
}
//search the element e in L, if exist return the location, else return 0
int LocateElem(char *L, char *e, int (*comp)(char a, char b)){
int i;
for(i = 0; *(L + i) != '\0'; ++i){
if(comp(*(L + i), *e)) return i + 1;
}
return 0;
}
//compare the element a and b
int compare(char a, char b){
if(a == b) return 1;
return 0;
}
//if e doesn't exit in L, insert the e in L
void ListInsert(char *L, int i, char *e){
int j;
for(j = ListLength(L) - 1; j >= i; --j){
*(L + j + 1) = *(L + j);
}
L[ListLength(L)] = '\0';
*(L + i - 2) = *e;
}
First, this is wrong:
char *La;
char *Lb;
int i;
for(i = 0; i <= 10; ++i){
La[i] = i;
Lb[i] = i + 5;
}
You need to reserve memory for La and Lb, for instance, by declaring them as:
char La[12];
char Lb[12];
An then this:
char *e;
for(i; i<= Lb_length; ++i){
GetElem(Lb, i, e);
should read:
char e;
for(; i<= Lb_length; ++i){
GetElem(Lb, i, &e); /* better yet: e=Lb[i] */
Finally, you're most likely looping one time too many by using <= instead of < as the for exit condition.
You have several issues. I think you need to read more about what are raw pointers, fixed length arrays, variable length arras and dynamic arrays. If you need your array to grow you can make it dynamic with malloc and realloc. Alternatively you can use a "big" array you know never will overflow.
int La[12]; // 0 to 10, plus '\0'
But this is fixed and cannt grow. You could use
int La[1000]; // if it solve yours problems
But in general you will need dynamic arrays.
Also, you need to deside if your array can hold 0 or it is used as terminator. '\0' and 0, in the form you use it are equal. Many of your for cycle dont run because the first elemnt is 0.

Problems with implementation of concatenation function in C

I am still new to pointers in C and have been trying to make string functions. This one is supposed to concatenate two strings, but when I try to run it, it crashes.
void concatenate (char *a, char *b, int size_a, int size_b) {
char *c, *d, *e;
c = a;
d = b;
int i, j, k;
int l = 1;
for(i = 0; i<size_a; i++) {
*(e+i) = *(c+i);
}
for (j = size_a; j<size_a+size_b; j++) {
*(e+j) = *(d+(j-(j-l)));
l++;
}
for (k = 0; k< size_a+size_b; k++){
printf("%c",*(e+k));
}
}
What am I doing wrong?
You are trying to access the memory where uninitialized pointer e points to, which leads to undefined behavior.
Your function should look like this:
char* concatenate (const char *a, const char *b, int size_a, int size_b) {
// create new string:
char* newStr = malloc (size_a + size_b + 1);
int i, j;
// copy first string into it:
for (i = 0; i<size_a; i++)
newStr[i] = a[i];
// copy second string into it:
for (j = 0; j < size_b; j++)
newStr[i + j] = b[j];
newStr[i + j] = '\0';
return newStr;
}
Note that function doesn't change strings that are passed to it, thus they can be passed as const. The size_a and size_b are expected to be equal to strlen(a) and strlen(b), which also means that in case you always pass null-terminated strings into this function, you can calculate their length on your own within its body (so you can get rid of last 2 arguments).
e is an uninitialized pointer, which means it is pointing to some random place in memory. When you start writing to it as if it were a pointer to a character array, your program will crash (or worse, change some state mysteriously causing unspecified behavior later on).
Your code seems obfuscated for no reason. The problem is that you're assigning to e, which is uninitialized. The following is, pretty much, your code in a more readable form and with e allocated. I haven't tested it, though.
void concatenate (char *c, char *d) {
char *e;
e = calloc(strlen(c) + strlen(d) + 1, sizeof(char));
int i, j;
int l = 1;
for(i = 0; c[i]; i++) {
e[i] = c[i];
}
l = i;
for (j = 0; d[j]; j++) {
e[l + j] = d[j];
}
e[l + j] = '\0';
printf("%s", e);
free(e);
}

Resources