Can someone help me with the pointer version of this function - c++

I'm having trouble trying to come up with the pointer version of this function:
void strncpy(char t[], const char s[], const unsigned int n)
{
unsigned int i = 0;
for(i = 0; i < n and s[i]; i++)
t[i]=s[i];
t[i] = '\0'
}
This function is supposed to copy the first "n" characters of one array to another array and then terminate with a null character. I'm sure this is simple but I'm still learning pointers :P
This is what I have right now:
void strncpy(char * t, const char * s, const unsigned int * n)
{
unsigned int i = 0;
for(i = 0; i < *n and *s; i++)
*t = *s;
*t = '\0';
}
Im calling it in main via:
char array_one[5] = "quiz";
char array_two[5] = "test";
unsigned int x = 2;
strncpy(array_one,array_two,x);

You've failed to increment the pointers, so you're always overwriting the same address. There's also no need to pass n via a pointer:
#include <cstddef>
void my_strncpy(char *t, const char *s, std::size_t n) {
while (n && *s) {
*t++ = *s++;
--n;
}
*t = '\0';
}
NB: note use of size_t to duplicate the standard parameter signature
of the standard strncpy function, although the standard version also returns the original value of t rather than void.

#include <iostream>
// changing the function signature to take an int instead of
// pointer to int - cleaner
void my_strncpy(char * t, const char * s, const unsigned int n)
{
unsigned int i = 0;
for(i = 0; i < n; i++)
{
*t++ = *s++; // copy and increment
}
*t = '\0'; // fixing - added terminating char
}
int main(void)
{
char a[] = "string1";
char b[] = "string2";
my_strncpy(a,b,7); // replace 7 with appropriate size
std::cout << a << std::endl;
}
You need to copy over each character from one string to another and then increment the pointers - you were missing that in your implementation.
I also assume that you will not overshoot the array you are copying from.

Related

How to count characters in a C_String in C++?

I'm a new Computer Science student, and I have a homework question that is as follows:
Write a Function that passes in a C-String and using a pointer determine the number of chars in the string.
Here is my code:
#include <iostream>
#include <string.h>
using namespace std;
const int SIZE = 40;
int function(const char* , int, int);
int main()
{
char thing[SIZE];
int chars = 0;
cout << "enter string. max " << SIZE - 1 << " characters" << endl;
cin.getline(thing, SIZE);
int y = function(thing, chars, SIZE);
cout << y;
}
int function(const char *ptr, int a, int b){
a = 0;
for (int i = 0; i < b; i++){
while (*ptr != '\0'){
a++;
}
}
return a;
}
First of all welcome to stackoverflow ye0123! I think you are trying to rewrite the strlen() function here. Try giving the following link a look Find the size of a string pointed by a pointer.
The short answer is that you can use the strlen() function to find the length of your string. The code for your function will look something like this:
int function(const char *ptr)
{
size_t length = strlen(ptr);
return length;
}
You should also only need this function and main.
Edit: Maybe I misunderstood your question and you are supposed to reinvent strlen() after all. In that case, you can do it like so:
unsigned int my_strlen(const char *p)
{
unsigned int count = 0;
while(*p != '\0')
{
count++;
p++;
}
return count;
}
Here I am comparing *p from '\0' as '\0' is the null termination character.
This was taken from https://overiq.com/c-programming-101/the-strlen-function-in-c/

Passing a pointer by reference

#include <iostream>
using namespace std;
void merge(int *& toMerge, int lo, int mid, int hi)
{
int merged[hi+1];
int i = lo, j = mid+1;
for (int k = lo; k <= hi; k++)
{
if (i > mid) {merged[k] = toMerge[j]; j++;}
else if (j > hi) {merged[k] = toMerge[i]; i++;}
else if (toMerge[j] < toMerge[i]) {merged[k] = toMerge[j]; j++;}
else {merged[k] = toMerge[i]; i++;}
}
toMerge = merged;
}
int main(int argc, const char * argv[])
{
int x[8] = {1,7,4,6,2,7,3,2};
merge(x, 0, 7, 3);
return 0;
}
I am trying to pass a pointer by reference here such that the end result will be that the array x will be sorted. However, my compiler is throwing an error that there is no matching function call for the merge(x, 0, 7, 3).
I am not sure as to why this is happening because the merge function requires a pointer, and x is a pointer to the first element in the array -- so it should work. Why doesn't it?
An array decays to a pointer when you pass it as an argument to a function call but not to a reference to a pointer.
Imagine this:
void foo(int*& p)
{
p = new int;
}
int main()
{
int arr[6] = {0};
foo(arr);
// You don't want arr to be an invalid object here.
// If the compiler allowed you to do that, that's what will happen.
// Not only that, foo(arr); is equivalent to:
// arr = new int;
// which is not allowed in the language.
}
You really should NOT pass a reference, because you don't really want merge changing the value of the pointer. You just want to allow it to change the values stored in the array, which it can do without the reference (i.e., just from the pointer).

C++ qsort 2D array

I am still getting lldb error, because i am probably accessing memory, that i shouldn't.
It looks like i am doing something wrong when manipulating with parameters in io_seg_sort, because before calling qsort, it is still ok.
#define IO_SEG_IMAX (IO_SEG - 1)
static int io_seg_sort (const void * seg1, const void * seg2) {
int * _seg1 = (int *)seg1;
int * _seg2 = (int *)seg2;
cout << _seg1[1] <<endl; // this gives some random values and not what i am expecting
if (_seg1[1] > _seg2[1]) {
return 1;
}
else if (_seg1[1] < _seg2[1]) {
return -1;
}
else {
return 0;
}
}
int **temp = new int *[IO_SEG];
for (int i = 0; i <= IO_SEG_IMAX; i++) {
temp[i] = new int[2];
memcpy(temp[i], inputs[i], sizeof(int) * 2);
}
qsort(temp, IO_SEG, sizeof(int *) , io_seg_sort);
EDIT1: the problem is i am getting some random values in io_seg_sort when calling cout instead of what i am expecting. inputs[i] is class member int inputs[IO_SEG][2];
You're putting IO_SEG_MAX + 1 items into an array that's IO_SEG long.
for (int i = 0; i <= IO_SEG_IMAX; i++) {
temp[i] = new int[2];
memcpy(temp[i], inputs[i], sizeof(int) * 2);
}
That should be:
for (int i = 0; i < IO_SEG; i++) {
temp[i] = new int[2];
memcpy(temp[i], inputs[i], sizeof(int) * 2);
}
But if you really intend to do this in C++, you should look into std::vector and std::sort.
The primary reason your code prints garbage is that you have mismatched levels of indirection inside the comparison function. Your temp array that you pass to qsort consists of pointers to two-element arrays. That means that inside the comparison function you actually receive pointers to pointers to int. I.e. this is already incorrect
static int io_seg_sort (const void * seg1, const void * seg2) {
int * _seg1 = (int *)seg1;
int * _seg2 = (int *)seg2;
cout << _seg1[1] <<endl;
You have to do something like
static int io_seg_sort (const void * seg1, const void * seg2) {
const int * _seg1 = *(const int *const *) seg1;
const int * _seg2 = *(const int *const *) seg2;
to get access to your arrays through _seg1 and _seg2 as you do it in the body of io_seg_sort (I also added some const qualifiers, although they are not required for the code to work.)

qsort in C++ for string arrays?

I'm working on a program that takes a list of words entered by the user, ignores the cases (upper and lower) and then sorts them using the function qsort. I'm having an issue with qsort in that I don't know what to pass as the 3rd item qsort(array, sizeOfArray, ??, funcCompare). Can somebody point me in the right direction?
using namespace std;
int compare(const void* , const void*);
const int SIZE = 100;
void main()
{
int i = 0;
int s = 0;
size_t size = 0;
string words;
string list[SIZE];
for (i = 0; i < SIZE; i++)
{
cout << "Please enter a word. Press ^Z to quit: " << endl;
cin >> words;
transform(words.begin(), words.end(), words.begin(), ::tolower);
if (words.length() > size)
{
size = words.length();
}
list[i] = words;
if (cin.eof())
{
s = i;
break;
}
}
qsort(list, s, ?? , compare);
for (int j = 0; j < i; j++)
{
cout << list[j] << endl;
}
}
int compare(const void* p1, const void *p2)
{
char char1, char2;
char1 = *(char *)p1; // cast from pointer to void
char2 = *(char *)p2; // to pointer to int
if(char1 < char2)
return -1;
else
if (char1 == char2)
return 0;
else
return 1;
}
The spot in question in qsort has the '??' Any help you can give is appreciated!
This is an assignment
Technically you need to pass sizeof(string)
But std::string is not trivial type and thus you are not allowed to use qsort to sort array of strings.
25.5 C library algorithms
4 The function signature:
qsort(void *, size_t, size_t, int (*)(const void *, const void ));
is replaced by the two declarations:
extern "C" void qsort(void base, size_t nmemb, size_t size, int (compar)(const void, const void*));
extern "C++" void qsort(void* base, size_t nmemb, size_t size, int (compar)(const void, const void*));
both of which have the same behavior as the original declaration. The behavior is undefined unless the
objects in the array pointed to by base are of trivial type.
If you are using C++ and std::string you should use also std::vector instead of plain array and std::sort instead of qsort.
You need to pass the size of each element in the array, in bytes.
This is accomplished by: sizeof(string)
qsort(list, s, sizeof(string), compare);
EDIT: Take a look at alexrider's post for more information on this
I wrote a qsort string comparision function a while back for BRL-CAD, here is the compare function used(keep in mind written in C, could be optimized).
* Sort function called by quick sort to sort data according
* to its second field in the string
*/
int
sort(const void* a, const void* b)
{
char *ia = *(char**)a;
char *ib = *(char**)b;
char Str[MAX_RESULT_LEN];
char Str2[MAX_RESULT_LEN];
//get string into array
GetStr(ia, Str);
GetStr(ib, Str2);
int n1 = atoi(Str);
int n2 = atoi(Str2);
return (n2 - n1);
}

How do you do change from one variable to another?

I have a few questions:
How do you get a certain char from a string?
How do you get a char to a int?
How do you get a int to a char?
How do you append a char to a string?
I was just making a simple keyed cipher... just playing around to learn cpp. I do know java so if you could relate to that it would be great!
Here is my code so please tell me how to improve... thanks! :)
#include <string>
using namespace std;
string encrypt(string data, string pass) {
// Use a Keyed Cipher //
string encrypted;
int index = 0;
for (int x = 0; x < sizeof(data); x++) {
int tmp = static_cast<int>(data.substr(x));
int tmpPass = static_cast<int>(pass.substr(index));
tmp += tmpPass;
if (tmp > 126) {
tmp -= 95;
}
if (index > sizeof(pass)) {
index = 0;
}
encrypted += static_cast<char>(tmp);
}
return data;
}
How do you get a certain char from a string?
By using index operator. string::operator[]
How do you get a char to a int?
int charToInteger = stringName[i] ;
How do you append a char to a string?
Using string::append
From the link -
string& append ( size_t n, char c );
Appends a string formed by the repetition n times of character c.
First of all with a string: const char& operator[] ( size_t pos ) const; e.g.:
char tmp = encrypted[x];
For conversion, you can just use C-style conversions:
int tmp = (int)encrypted[x];
This should generally work, as long as you're using an architecture with sizeof(char) <= sizeof(int) (e.g. some Texas Instruments calculators :)
But, in your code, you can just operate with chars, because chars can also be used as numeric types.
The easiest way to append a char to string is using += :
string s = "Hello worl";
s += 'd';
How do you get a certain char from a string?
the class "string" implements the operator [], so to get the "i" char you can use mystring[i].
std::string has a function called "c_str()" which returns "const char*" that is inside the string.
so another way to get a char from a std::string is *(mystring.c_str()+i).
How do you get a char to a int?
char is a 1 byte data type, so you can cast char into an int just like in java.
char c = 'a';
int i = (int)c;
How do you get a int to a char?
just like in Java. notice that int is usually 4 bytes (doesn't have to be 4 bytes!!!), so you might lose data because char is 1 byte.
int i=0xFFFF
char c = (char)i;
c is 0xFF! lost some data!
How do you append a char to a string?
std::string implements operator += so you can use it.
string s = "foo"; char c=s[1];
char c = 'a'; int i = c;
int i = 65; char c = (char) i;
string s = "foo"; char c = 'X'; s += c;
for (int x = 0; x < sizeof(data); x++) won't work - use data.size() not sizeof(data)
int tmp = static_cast<int>(data.substr(x)); won't work either. If you want the ascii value of data[x] just do int tmp = data[x];
if (index > sizeof(pass)) won't work - you need to use pass.size()
And finally, you never increase index within the loop, and you return the wrong string.
#include <string>
using namespace std;
string encrypt(string const & data, string const & pass) { // Pass arguments by const reference, not as values which are copied
// Use a Keyed Cipher //
string encrypted;
int index = 0;
for (int x = 0; x < data.size(); ++x) { // Loop over the length of the string, not the size of the string object
int tmp = data[x]; // No need to cast
int tmpPass = pass[index]; // No need to cast
tmp += tmpPass;
if (tmp > 126) {
tmp -= 95;
}
++index; // Remember to loop over the password as well
if (index >= pass.size()) { // Check against length of string, not size of object
index = 0;
}
encrypted += static_cast<char>(tmp);
}
return encrypted; // Return the encrypted string
}