Best way to interleave two char arrays - pointers

I am looking for the best way to interleave two char arrays using a function that were input by the user. I am learning C++ and this is a homework so I can't use anything too advance assignment I am just curious if I am going the right direction with it.
I was thinking that using a for loop to iterate through each index in both arrays and then use the function to add the two chars and output them. I also have to use pointers for this assignment.
#include <iostream>;
using namespace std;
char* strinterleave(const char *a, const char *b) {
char done;
done = *a + *b;
}
int main() {
char interleave[]="";
char storage1[] = "";
char storage2[] = "";
int lena;
int lenb;
char *a_ptr = storage1;
char *b_ptr = storage2;
cin.getline(storage1, numeric_limits<streamsize>::max(), ' ');
cin.getline(storage2, numeric_limits<streamsize>::max());
lena = strlen(a_ptr);
lenb = strlen(b_ptr);
int finallen = lena + lenb;
for (int j = 0; j <= finallen; ++j) {
strinterleave(a_ptr[j], b_ptr[j]);
}
}
Is this the wrong way to go about this and if so what would be the right direction to go?
Thank you

Here are some things to consider:
The string lengths may not be the same. You'll need to decide what do with any remaining characters in the longer string.
Examining your code...
int finallen = lena + lenb;
for (int j = 0; j <= finallen; ++j) { <--- Remember you are processing two characters at once, so you probably want something like the max of lena or lenb.
strinterleave(a_ptr[j], b_ptr[j]); // <--- this is passing chars, not pointers to chars, so it doesn't match the function declaration.
char* strinterleave(const char *a, const char b) { //<- Make this just chars, not char)
char done;
done = *a + *b; <-- Adding the characters won't interleave them. I'm guessing your instructor wants a new string created with the characters interleaved.
For instance if you have:
storage1 = "123456"
storage2 = "abc"
The instructor probably wants:
finalString = "1a2b3c456"
}

Related

Do I need to malloc C-style strings?

I recently started using Arduino so I still have to adapt and find the differences between C/C++ and the Arduino language.
So I have a question for you.
When I see someone using a C-style string in Arduino (char *str), they always initialize it like this (and never free it) :
char *str = "Hello World";
In pure C, I would have done something like this:
int my_strlen(char const *str)
{
int i = 0;
while (str[i]) {
i++;
}
return (i);
}
char *my_strcpy(char *dest, char const *src)
{
char *it = dest;
while (*src != 0) {
*it = *src;
it++;
src++;
}
return (dest);
}
char *my_strdup(char const *s)
{
char *result = NULL;
int length = my_strlen(s);
result = my_malloc(sizeof(char const) * (length + 1));
if (result == NULL) {
return (NULL);
}
my_strcpy(result, s);
return (result);
}
and then initialize it like this:
char *str = my_strdup("Hello World");
my_free(str);
So here is my question, on C-style Arduino strings, is malloc optional or these people just got it wrong?
Thank you for your answers.
In C++ it's better to use new[]/delete[] and not mix it with malloc/free.
In the Arduino there is also String class, that hides those allocations from you.
However using dynamic memory allocations in such restrained platform has its pitfalls, like heap fragmentation (mainly because String overloads + operator, so everyone is overusing it like: Serial.println(String{"something : "} + a + b + c + d + ......) and then wonders about mysterious crashes.
More about it on Majenko's blog: The Evils of Arduino String class (Majenko has highest reputation on the arduino stackexchange)
Basically with the String class your strdup code would be simple as this:
String str{"Hello World"};
String copyOfStr = str;

How does one use qsort to sort a char containing pathnames/files based on their bytes?

I basically wrote a code in which I take two command line arguments one being the type of file that I want to search in my directory and they other being the amount I want(which is not implemented yet, but I can fix that)
The code is like so:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#define sizeFileName 500
#define filesMax 5000
int cmpfunc( const void *a, const void *b) {
return *(char*)a + *(char*)b;
}
int main( int argc, char ** argv) {
FILE * fp = popen( "find . -type f", "r");
char * type = argv[1];
char * extension = ".";
char* tExtension;
tExtension = malloc(strlen(type)+1+4);
strcpy(tExtension, extension);
strcat(tExtension, type);
// printf("%s\n",tExtension);
int amount = atoi(argv[2]);
//printf("%d\n",amount);
char buff[sizeFileName];
int nFiles = 0;
char * files[filesMax];
while(fgets(buff,sizeFileName,fp)) {
int leng = strlen(buff) - 1;
if (strncmp(buff + leng - 4, tExtension, 4) == 0){
files[nFiles] = strndup(buff,leng);
//printf("\t%s\n", files[nFiles]);
nFiles ++;
}
}
fclose(fp);
printf("Found %d files\n", nFiles);
long long totalBytes = 0;
struct stat st;
// sorting based on byte size from greatest to least
qsort(files, (size_t) strlen(files), (size_t) sizeof(char), cmpfunc);
for(int i = 0;i< nFiles; i ++) {
if(0!= stat(files[i],&st)){
perror("stat failed:");
exit(-1);
}
totalBytes += st.st_size;
printf("%s : %ld\n",files[i],st.st_size);
}
printf("Total size: %lld\n", totalBytes);
// clean up
for(int i = 0; i < nFiles ; i ++ ) {
free(files[i]);
}
return 0;
}
So far I have every section set up properly, upon running the code say $./find ini 5, it would print out all the ini files followed by their byte size(it's currently ignore the 5). However, for the qsort(), I'm not exactly sure how I would sort the contents of char * files as while it holds the pathnames, I had to use stat to get the byte sizes, how would I print out a sorted version of my print statements featuring the first statement being the most bytes and finishes at the least bytes?
If we suppose your input is valid, your question could be simplified with:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define filesMax 5000
int cmpfunc(const void const *a, const void *b) { return *(char *)a + *(char *)b; }
int main(void) {
int nFiles = 4;
char *files[filesMax] = {"amazing", "hello", "this is a file", "I'm a bad file"};
qsort(files, strlen(files), sizeof(char), cmpfunc);
for (int i = 0; i < nFiles;; i++) {
printf("%s\n", files[i]);
}
}
If you compile with warning that give you:
source_file.c:11:23: warning: incompatible pointer types passing 'char *[5000]' to parameter of type 'const char *' [-Wincompatible-pointer-types]
qsort(files, strlen(files), sizeof(char), cmpfunc);
^~~~~
qsort() expect the size of your array (or in your case a subsize) and it's also expect the size of one element of your array. In both you wrongly give it to it. Also, your compare function doesn't compare anything, you are currently adding the first bytes of both pointer of char, that doesn't make a lot of sense.
To fix your code you must write:
qsort(files, nFiles, sizeof *files, &cmpfunc);
and also fix your compare function:
int cmpfunc_aux(char * const *a, char * const *b) { return strcmp(*a, *b); }
int cmpfunc(void const *a, void const *b) { return cmpfunc_aux(a, b); }
also size should be of type size_t:
size_t nFiles = 0;
Don't forget that all informations about how to use a function are write in their doc.
how would I print out a sorted version of my print statements featuring the first statement being the most bytes and finishes at the least bytes?
Your code don't show any clue that your are trying to do that, you are currently storing name file and only that. How do you expect sort your file with an information you didn't acquired ?
However, that simple create a struct that contain both file name and size, acquire information needed to sort it and sort it:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <inttypes.h>
struct file {
off_t size;
char *name;
};
int cmpfunc_aux(struct file const *a, struct file const *b) {
if (a->size > b->size) {
return -1;
} else if (a->size < b->size) {
return 1;
} else {
return 0;
}
}
int cmpfunc(void const *a, void const *b) { return cmpfunc_aux(a, b); }
#define filesMax 5000
int main(void) {
size_t nFiles = 4;
struct file files[filesMax] = {{42, "amazing"},
{21, "hello"},
{168, "this is a file"},
{84, "I'm a bad file"}};
qsort(files, nFiles, sizeof *files, &cmpfunc);
for (size_t i = 0; i < nFiles; i++) {
printf("%s, %" PRId64 "\n", files[i].name, (intmax_t)files[i].size);
}
}
The function cmpfunc() provided adds the first character of each string, and that's not a proper comparison function (it should give a opposite sign value when you switch the parameters, e.g. if "a" and "b" are the strings to compare, it adds the first two characters of both strings, giving 97+98 == 195, which is positive on unsigned chars, then calling with "b" and "a" should give a negative number (and it again gives you 98 + 97 == 195), more on, it always gives the same result ---even with signed chars--- so it cannot be used as a sorting comparator)
As you are comparing strings, why not to use the standard library function strcmp(3) which is a valid comparison function? It gives a negative number if first string is less lexicographically than the second, 0 if both are equal, and positive if first is greater lexicographically than the second.
if your function has to check (and sort) by the lenght of the filenames, then you can define it as:
int cmpfunc(char *a, char *b) /* yes, you can define parameters as char * */
{
return strlen(a) - strlen(b);
}
or, first based on file length, then lexicographically:
int cmpfunc(char *a, char *b)
{
int la = strlen(a), lb = strlen(b);
if (la != lb) return la - lb;
/* la == lb, so we must check lexicographycally */
return strcmp(a, b);
}
Now, to continue helping you, I need to know why do you need to sort anything, as you say that you want to search a directory for a file, where does the sorting take place in the problem?

seg fault / pointer assistance

so i know the bases of programming, i have a decent amount of experience with java, but im learning C for school right now. I still dont completely understand the whole pointer aspect, which is what im sure caused the fault. This program works fine when run on my computer, but when i try and run it on my schools unix shell it gives me a seg fault. if someone could please explain to me why or how ive misused hte pointers, that would help me greatly.
//Matthew Gerton
//CS 222 - 002
//10/10/14
//HW Six
//libraries
#include<stdio.h>
#include<string.h>
#define max_Length 256
//prototypes
void decode(char *a, char *b);
void trimWhite(char *a);
void encode(char *a, char *b);
int main(void)
{
//character arrays
char coded[max_Length], decoded[max_Length];
//decode the sample phrase
char sample[] = {'P','H','H','W','D','W','C','R','R','F','D','Q','F','H','O','H','G','J',
'R','W','R','P','H','W','U','R','K','R','W','H','O','U','R','R','P','I','R','X','U'};
decode(sample, decoded);
//scans a user input string to decode, and decodes it
printf("\nPlease enter a phrase to decode: ");
gets(coded);
trimWhite(coded);
decode(coded, decoded);
//scans a user input phrase to encode
printf("\nPlease enter a phrase to encode: ");
gets(coded);
trimWhite(coded);
encode(coded, decoded);
}
//removes any spaces from the input
void trimWhite(char *a)
{
char temp[max_Length];
int z=0, y=0;
while(a[z]!='\0')
{
if(a[z]!=' ')
{
temp[y]=a[z];
y++;
}
z++;
}
temp[y] = '\0';
strcpy(a,temp);
}
//decodes any phrase
void decode(char *a, char *b)
{
int i=0,n;
memset(b, '\0', sizeof(b));
while(a[i]!='\0')
{
n=(int)a[i];
if(n<97)
n=n+32;
if(n<=99)
n=n+23;
else
n = n-3;
b[i]= (char) n;
i++;
}
b[i]='\0';
printf("Coded message: %s\n", a);
printf("Decoded message: %s\n", b);
}
//codes an input phrase
void encode(char *a, char *b)
{
int i=0,n;
memset(b, '\0', sizeof(b));
strcpy(b,a);
while(a[i]!='\0')
{
n=(int)a[i];
if(n<97)
a[i] = (char)(n+32);
if((n>120)
a[i] = (char)(n-23);
else
a[i] = (char)((n+3);
i++;
}
printf("Coded message: %s\n", a);
}
Your main problem is here:
char sample[] = {'P','H','H', /* snip */ ,'R','X','U'};
The sample[] array is not zero-terminated which may cause the decode() function to copy many more characters than intended, thus overwriting other variables. You need to explicitly add a terminating zero when using an initializer-list:
char sample[] = {'P','H','H', /* ... */ ,'R','X','U',0};
Or you can initialize the array using a string literal, which does include a terminating zero:
char sample[] = "PHHWDWCRRFDQFHOHGJRWRPHWURKRWHOURRPIRXU";
You should probably read "Why is the gets function dangerous".
...
void decode(char *a, char *b)
{
int i=0,n;
memset(b, '\0', sizeof(b));
Also note that the size of the array is lost when it is passed to a function. The function only receives a pointer to its first element. The memset() call above will only zero sizeof(char*) bytes (usually 4 or 8). This doesn't matter though because, as far as I can tell, you only need to zero the first byte. You could simply write:
b[0] = 0;

Need help copying a char array into an array struct with char pointer

I'm trying to copy char array word to char pointer s[1].c, an then another word to char pointer s[2].c but when i'm trying to do that , the second word appears to be copied in all two pointers . How can i fix that ? I don't want to use strings .
struct Stud {
char *c;
} s[100];
char word[32];
int main()
{
strcpy(word,"one");
s[1].c=word;
word={0};
strcpy(word,"two");
s[2].c=word;
cout<<s[1].c<<" "<<s[2].c;
return 0;
}
In your code you are setting s[1].c = word; which means you are setting s[1].c to the address of word. Then you set s[2].c = word; which is the same exact memory location. (With c strings, (char *)s1 = (char *)2 does not do a string copy as you might expect. It just assigns one pointer to another).
With strdup you allocate a new memory block and then copy the string into the allocated space.
Here's your code modified.
struct Stud
{
char *c;
} s[100];
int main()
{
char word[32];
strcpy(word, "one");
s[0].c = strdup(word); // In C/C++ the first array index is 0
strcpy(word, "two");
s[1].c = strdup(word);
// Should check to make sure s[0].c and s[1].c are not NULL....
cout << s[0].c << " " <<s [1].c;
free(s[0].c);
free(s[1].c);
return 0;
}

Why can't I use the -> operator for a struct pointer in main?

I thought that the general rule of thumb was that the -> operator was used for accessing members of struct pointers, and the . operator was used for accessing members of an actual struct. In my code, I thought I created a struct pointer, but I ended up still having to use the . operator. Can someone explain why?
typedef struct Robot
{
char **brain;
int size;
} Robot;
int main(void)
{
char buffer[100];
Robot *dalek = malloc(sizeof(Robot)*2);
for(i = 0; i < 2; i++)
dalek[i].brain = malloc(sizeof(char*) * 3);
for(i = 0; i < 3; i++)
{
scanf("%s", buffer);
dalek[0].brain[i] = malloc(sizeof(char) * strlen(buffer));
strcpy(dalek[0].brain[i], buffer);
}
}
dalek is a pointer, and dalek[i] is equivalent to *(dalek + i), i.e. it dereferences. If you want to use the arrow, say (dalek + i)->brain etc.
dalek[i] is defined as *(dalek+i). So when you do dalek[i]->brain you are really doing *(*(dalek+i)).brain, dereferencing a single pointer twice. If you really want to use the -> operator, you could use (dalek+i)->brain.

Resources