I need to write void strncat which appends the first num characters of source to destination, plus a terminating null-character. If the length of the C string in source is less than num, only the content up to the terminating null-character is copied. What am i doing wrong?
#include <iostream>
#include <cstring>
#include <string>
using namespace std;
const int MAXDESTINATION = 40;
const int MAXSOURCE = 150;
int main() {
char dest[MAXDESTINATION + 1] = "It don't mean a thing";
char src[MAXSOURCE + 1] = " if it don't got the Go-Go swing!";
int a = strlen(dest);
int b = strlen(src);
strncat(dest, src, MAXDESTINATION - a) ;}
void strncat(char destination[], const char source[], int num) {
if (int strlen(source) < num) {
int begin = 0;
bool less = false;
for (int i = 0; i <num; i++) {
if (destination[i] == '\0') {
begin = i;
less = true;
}
if (less == true) {
destination[begin] = source[i];
}
}
}
I'm guessing (since you haven't provided even the full definition of strncat) your problem is that you're not incrementing begin. The way it's written right now, the same spot is overwritten each time with the value at source[i]
You maybe want to say
destination[begin++] = source[i];
or maybe you should just use i instead, as begin should probably track i exactly, as it's initialized to i and then should be incremented once every time i is.
Also, from an efficiency standpoint, you're iterating over source multiple times. Once with your call to strlen (which has to go through each letter in the string to count them) and then again in your for loop. You should look to remove the strlen.
Compile errors:
error C1075 :end of file found before the left brace '{' ...
error c4996: 'strncat': this function or variable may be unsafe. consider using strncat_s instead.
Related
I'm trying to implement a void function that takes a c string as its only parameter and reverses it and prints it. Below is my attempt at a solution however I'm not sure how to go about this problem.
void printBackwards(char forward[]) {
int i = 0;
char backwards[];
while (forward[i] != '\0') {
backwards[i] = forward[-i - 1];
i++;
}
cout << backwards;
}
Under such a condition, I guess you are expected to use recursion.
void printBackwards(char forward[]) {
if (!forward[0])
return;
printBackwards(forward + 1);
cout << forward[0];
}
Not being able to use strlen, we'll calculate it ourselves using a simple for loop. Then dynamically allocate a suitable buffer (add one character for the null terminating char, and I "cheated" by using calloc to zero the memory so I don't have to remember to set the null terminator. Then anoher simple loop to copy the original into the result in reverse.
#include <stdlib.h>
#include <stdio.h>
char *rev(char *s) {
size_t i;
char *s2 = s; // A pointer to the beginning as our first loop modifies s
for (i = 0; *s; s++, i++);
char *result = calloc(0, i + 1);
if (!result) return NULL; // In case calloc didn't allocate the requested memory.
for (size_t j = 0; j < i; j++)
result[j] = s2[i - j - 1];
return result;
}
Assuming you want to reverse the string rather than just printing it in reverse order, you first need to find the last character location (actually the position of the null terminator). Pseudo-code below (since this is an educational assignment):
define null_addr(pointer):
while character at pointer is not null terminator:
increment pointer
return pointer
Then you can use that inside a loop where you swap the two characters and move the pointers toward the center of the string. As soon as the pointers become equal or pass each other the string is reversed:
define reverse(left_pointer):
set right_pointer to null_addr(left_pointer)
while right_pointer > left_pointer plus one:
decrement right_pointer
swap character at left_pointer with character at right_pointer
increment left_pointer
Alternatively (and this appears to be the case since your attempt doesn't actually reverse the original string), if you need to print the string in reverse order without modifying it, you still find the last character. Then you run backwards through the string printing each character until you reach the first. That can be done with something like:
define print_reverse(pointer):
set right_pointer to null_addr(pointer)
while right_pointer > pointer:
decrement right_pointer
print character at right_pointer
That's probably better than creating a new string to hold the reverse of the original, and then printing that reverse.
One thing you should keep in mind. This very much appears to be a C-centric question, not a C++ one (it's using C strings rather than C++ strings, and uses C header files). If that's the case, you should probably avoid things like cout.
By using abstractions, like , your code will be much better at communication WHAT it is doing instead of HOW it is doing it.
#include <iostream>
#include <string>
#include <ranges>
int main()
{
std::string hello{ "!dlrow olleH" };
for (const char c : hello | std::views::reverse)
{
std::cout << c;
}
return 0;
}
Use a template
#include <iostream>
template<int N, int I=2>
void printBackwards(char (&forward)[N]) {
std::cout << forward[N-I];
if constexpr (I<N) printBackwards<N, I+1>(forward);
}
int main() {
char test[] = "elephant";
printBackwards(test);
}
While there seems to be several working answers, I thought I'd throw my hat in the stack (pun intended) since none of them take advantage of a FILO data structure (except #273K's answer, which uses a stack implicitly instead of explicitly).
What I would do is simply push everything onto a stack and then print the stack:
#include <stack>
#include <iostream>
void printBackwards(char forward[]) {
// Create a stack to hold our reversed string
std::stack<char> stk;
// Iterate through the string until we hit the null terminator
int i = 0;
while (forward[i] != '\0'){
stk.push(forward[i]);
++i;
}
// Iterate through the stack and print each character as we pop() it
while (stk.size() > 0){
std::cout << stk.top();
stk.pop();
}
// Don't forget the newline (assuming output lines should be separated)
std::cout << '\n';
}
int main(int argc, char* argv[]){
char s[] = "This is a string";
printBackwards(s);
return 0;
}
Hi guys as promised I have come back to add my own answer. This is my own way using array subscripts and using what I currently know.
#include <iostream>
using namespace std;
void printBackwards(char[]);
int main()
{
char word[] = "apples";
printBackwards(word);
return 0;
}
void printBackwards(char word[]) {
char* temp = word;
int count = 0;
while (*temp++ != '\0') {
count++;
}
for (int i = count - 1; i >= 0; i--) {
cout << word[i];
}
}
You can make a fixed-size buffer and create new ones if needed. Fill it reverse by moving the string offset back with every inserted character. Chars exceeding the buffer are returned to be processed later, so you can make a list of such buffers:
template<int SIZE>
struct ReversedCStr
{
static_assert(SIZE > 10); // just some minimal size treshold
// constexpr
ReversedCStr(char const* c_str, char const** tail = nullptr) noexcept
{
for(buffer[offset] = '\0'; *c_str != '\0';)
{
buffer[--offset] = *c_str++;
if(offset == 0) break;
}
if(tail) *tail = c_str;
}
//constexpr
char const* c_str() const noexcept { return buffer.data()+offset;};
private:
size_t offset = SIZE -1;
std::array<char,SIZE> buffer;
};
The tag is 'C++' so I assume you use C++ not C. The following code is C++11 so it should fit in every modern project. I posted the working example on godbolt.org.
It doesn't allocate memory, and is completely exception-free. The maximum memory wasted is {buffer_size + sizeof(char*)*number_of_chunks}, and can be easily turned into a list of reversed chunks like this:
char const* tail;
std::vector<ReversedCStr<11>> vec;
for(vec.emplace_back(str,&tail); *tail != '\0';)
vec.emplace_back(tail,&tail);
So I'm making a function that is similar to SubStr. This is an assignment so I cannot use the actual function to do this. So far I have created a function to take a string and then get the desired substring. My problem is returning the substring. In the function when I do Substring[b] = AString[b]; the substring is empty, but if I cout from inside the function I get the desired substring. So what is wrong with my code?
Here is a working demo: http://ideone.com/4f5IpA
#include <iostream>
using namespace std;
void subsec(char AString[], char Substring[], int start, int length);
int main() {
char someString[] = "abcdefg";
char someSubString[] = "";
subsec(someString, someSubString, 1, 3);
cout << someSubString << endl;
return 0;
}
void subsec(char AString[], char Substring[], int start, int length) {
for (int b = start; b <= length; b++) {
Substring[b] = AString[b];
}
}
Maybe this does what you're looking for? It's hard to say as your initial implementation used the length parameter as more of an end position.
#include <iostream>
using namespace std;
void subsec(char AString[], char Substring[], int start, int length)
{
const int end = start + length;
int pos = 0;
for(int b = start; b < end; ++b)
{
Substring[pos++] = AString[b];
}
Substring[pos] = 0;
}
int main()
{
char someString[50] = "abcdefghijklmnopqrstuvwxyz";
char someSubString[50];
subsec(someString, someSubString, 13, 10);
cout << someSubString << endl;
return 0;
}
There are several problems with the code:
1) The char arraysomeSubString has size 1 which cannot hold the substring.
2) The subsec is not correctly implemented, you should copy to the Substring from index 0.
Also remember to add \0 at the end of the substring.
void subsec(char AString[], char *Substring, int start, int length) {
int ii = 0;
for (int jj = start; jj <= length; jj++, ii++) {
Substring[ii] = AString[jj];
}
Substring[ii] = '\0';
}
You need to allocate more than 1 byte for someSubString i.e.
char someSubString[] = "xxxxxxxxxxxxxxxxxx";
or just
char someSubString[100];
if you know the max size you'll ever need.
Either would allocate enough space for the string you're copying to it. Then, you're not doing anything about the terminating 0 either. At the end of a C-style string there needs to be a terminating null to signify end of string. Otherwise cout will print something like;
abcdefgxxxxxxx
if you initialized with x's as I indicated.
There are a few problems with your code as it stands. Firstly, as your compiler is no doubt warning you, in C++ a string literal has type const char[], not just char[].
Secondly, you need to have enough space to store your substring. A good way to do this is for your function to allocate the space it needs, and then pass back a pointer to this memory. This is the way things are typically done in C code. The only thing is that you have to remember to delete the allocated array when you're done with it. (There are other, better ways to do this in C++, with things like smart pointers and wrapper objects, but those come later :-) ).
Thirdly, you'll have a problem if you request a length which is actually longer than the passed-in string -- you'll run off the end and start copying random memory (or just crash), which is definitely not what you want. C strings are terminated with a "nul byte" -- so you need to check whether you've come across this.
Speaking of the nul, you need to make sure that your substring ends with one.
Lastly, it's not really a problem but there's no need for the start parameter, you can just pass a pointer to the middle of the array if you want to.
char* substring(const char* str, int length)
{
// Allocate memory for substring;
char* subs = new char[length+1];
// Copy characters from given string
int i = 0;
while (i < length && str[i] != '\0') {
subs[i] = str[i];
i++;
}
// Append the nul byte
subs[i] = '\0';
return subs;
}
int main()
{
const char someString[] = "foobarbaz"; // Note -- must be const in C++
char* subs = substring(someString + 3, 3);
assert(strcmp(subs, "bar") == 0);
delete subs;
}
I wrote this code to reverse strings. It works well, but when I enter short strings like "american beauty," it actually prints "ytuaeb nacirema2." This is my code. I would like to know what is wrong with my code that prints a random 2 at the end of the string. Thanks
// This program prompts the user to enter a string and displays it backwards.
#include <iostream>
#include <cstdlib>
using namespace std;
void printBackwards(char *strPtr); // Function prototype
int main() {
const int SIZE = 50;
char userString[SIZE];
char *strPtr;
cout << "Please enter a string (up to 49 characters)";
cin.getline(userString, SIZE);
printBackwards(userString);
}
//**************************************************************
// Definition of printBackwards. This function receives a *
// pointer to character and inverts the order of the characters*
// within it. *
//**************************************************************
void printBackwards(char *strPtr) {
const int SIZE = 50;
int length = 0;
char stringInverted[SIZE];
int count = 0;
char *strPtr1 = 0;
int stringSize;
int i = 0;
int sum = 0;
while (*strPtr != '\0') {
strPtr++; // Set the pointer at the end of the string.
sum++; // Add to sum.
}
strPtr--;
// Save the contents of strPtr on stringInverted on inverted order
while (count < sum) {
stringInverted[count] = *strPtr;
strPtr--;
count++;
}
// Add '\0' at the end of stringSize
stringInverted[count] == '\0';
cout << stringInverted << endl;
}
Thanks.
Your null termination is wrong. You're using == instead of =. You need to change:
stringInverted[count] == '\0';
into
stringInverted[count] = '\0';
// Add '\0' at the end of stringSize
stringInverted[count] == '\0';
Should use = here.
What is wrong with your code is that you do not even use strlen for counting the length of the string and you use fixed size strings (no malloc, or, gasp new[]), or the std::string (this is C++)! Even in plain C, not using strlen is always wrong because it is hand-optimized for the processor. What is worst, you have allocated the string to be returned (stringInverted) from the stack frame, which means when the function exits, the pointer is invalid and any time the code "works" is purely accidental.
To reverse a string on c++ you do this:
#include <iostream>
#include <string>
int main() {
std::string s = "asdfasdf";
std::string reversed (s.rbegin(), s.rend());
std::cout << reversed << std::endl;
}
To reverse a string in C99 you do this:
char *reverse(const char *string) {
int length = strlen(string);
char *rv = (char*)malloc(length + 1);
char *end = rv + length;
*end-- = 0;
for ( ; end >= rv; end --, string ++) {
*end = *string;
}
return rv;
}
and remember to free the returned pointer after use. All other answers so far are blatantly wrong :)
Okay, so I'm trying to reverse a C style string in C++ , and I'm coming upon some weird output. Perhaps someone can shed some light?
Here is my code:
int main(){
char str[] = "string";
int strSize = sizeof(str)/sizeof(char);
char str2[strSize];
int n = strSize-1;
int i =0;
while (&str+n >= &str){
str2[i] = *(str+n);
n--;
i++;
}
int str2size = sizeof(str)/sizeof(char);
int x;
for(x=0;x<str2size;x++){
cout << str2[x];
}
}
The basic idea here is just making a pointer point to the end of the string, and then reading it in backwards into a new array using pointer arithmetic.
In this particular case, I get an output of: " gnirts"
There is an annoying space at the beginning of any output which I'm assuming is the null character? But when I try to get rid of it by decrementing the strSize variable to exclude it, I end up with some other character on the opposite end of the string probably from another memory block.
Any ideas on how to avoid this? PS: (would you guys consider this a good idea of reversing a string?)
A valid string should be terminated by a null character. So you need to keep the null character in its original position (at the end of the string) and only reverse the non-null characters. So you would have something like this:
str2[strSize - 1] = str[strSize - 1]; // Copy the null at the end of the string
int n = strSize - 2; // Start from the penultimate character
There is an algorithm in the Standard Library to reverse a sequence. Why reinvent the wheel?
#include <algorithm>
#include <cstring>
#include <iostream>
int main()
{
char str[] = "string";
std::reverse(str, str + strlen(str)); // use the Standard Library
std::cout << str << '\n';
}
#ildjarn and #Blastfurnace have already given good ideas, but I think I'd take it a step further and use the iterators to construct the reversed string:
std::string input("string");
std::string reversed(input.rbegin(), input.rend());
std::cout << reversed;
I would let the C++ standard library do more of the work...
#include <cstddef>
#include <algorithm>
#include <iterator>
#include <iostream>
int main()
{
typedef std::reverse_iterator<char const*> riter_t;
char const str[] = "string";
std::size_t const strSize = sizeof(str);
char str2[strSize] = { };
std::copy(riter_t(str + strSize - 1), riter_t(str), str2);
std::cout << str2 << '\n';
}
while (&str+n >= &str){
This is nonsense, you want simply
while (n >= 0) {
and
str2[i] = *(str+n);
should be the much more readable
str2[i] = str[n];
Your while loop condition (&str+n >= &str) is equivalent to (n >= 0).
Your *(str+n) is equivalent to str[n] and I prefer the latter.
As HappyPixel said, your should start n at strSize-2, so the first character copied will be the last actual character of str, not the null termination character of str.
Then after you have copied all the regular characters in the loop, you need to add a null termination character at the end of the str2 using str2[strSize-1] = 0;.
Here is fixed, working code that outputs "gnirts":
#include <iostream>
using namespace std;
int main(int argc, char **argv){
char str[] = "string";
int strSize = sizeof(str)/sizeof(char);
char str2[strSize];
int n = strSize-2; // Start at last non-null character
int i = 0;
while (n >= 0){
str2[i] = str[n];
n--;
i++;
}
str2[strSize-1] = 0; // Add the null terminator.
int str2size = sizeof(str)/sizeof(char);
int x;
cout << str2;
}
I am trying to do some array manipulations.
I am doing char array sorting and duplicates removal here.
Your comments are welcome. Havent done much testing and error handling here though.
#include<stdafx.h>
#include<stdlib.h>
#include<stdio.h>
#include<string>
using namespace std;
void sort(char *& arr)
{
char temp;
for(int i=0;i<strlen(arr);i++)
{
for(int j=i+1;j<strlen(arr);j++)
{
if(arr[i] > arr[j])
{
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
}
bool ispresent(char *uniqueArr, char * arr)
{
bool isfound = false;
for(int i=0;i<strlen(arr);i++)
{
for(int j=0;j<=strlen(uniqueArr);j++)
{
if(arr[i]== uniqueArr[j])
{
isfound = true;
return isfound;
}
else
isfound = false;
}
}
return isfound;
}
char * removeduplicates(char *&arr)
{
char * uniqqueArr = strdup(""); // To make this char array modifiable
int index = 0;
bool dup = false;
while(*arr!=NULL)
{
dup = ispresent(uniqqueArr, arr);
if(dup == true)
{}//do nothing
else// copy the char to new char array.
{
uniqqueArr[index] = *arr;
index++;
}
arr++;
}
return uniqqueArr;
}
int main()
{
char *arr = strdup("saaangeetha");
// if strdup() is not used , access violation writing to
//location occurs at arr[i] = arr[j].
//This makes the constant string modifiable
sort(arr);
char * uniqueArr = removeduplicates(arr);
}
If you use std::string, your code (which is actually C-Style) can be written in C++ Style in just these lines:
#include <iostream>
#include <string>
#include <algorithm>
int main() {
std::string s= "saaangeetha";
std::sort(s.begin(), s.end());
std::string::iterator it = std::unique (s.begin(), s.end());
s.resize( it - s.begin());
std::cout << s ;
return 0;
}
Output: (all duplicates removed)
aeghnst
Demo : http://ideone.com/pHpPh
If you want char* at the end, then you can do this:
const char *uniqueChars = s.c_str(); //after removing the duplicates!
If I were doing it, I think I'd do the job quite a bit differently. If you can afford to ignore IBM mainframes, I'd do something like this:
unsigned long bitset = 0;
char *arr = "saaangeetha";
char *pos;
for (pos=arr; *pos; ++pos)
if (isalpha(*pos))
bitset |= 1 << (tolower(*pos)-'a');
This associates one bit in bitset with each possible letter. It then walks through the string and for each letter in the string, sets the associated bit in bitset. To print out the letters once you're done, you'd walk through bitset and print out the associated letter if that bit was set.
If you do care about IBM mainframes, you can add a small lookup table:
static char const *letters = "abcdefghijklkmnopqrstuvwxyz";
and use strchr to find the correct position for each letter.
Edit: If you're using C++ rather than C (as the tag said when I wrote what's above), you can simplify the code a bit at the expense of using some extra storage (and probably being minutely slower):
std::string arr = "saaangeetha";
std::set<char> letters((arr.begin()), arr.end());
std::copy(letters.begin(), letters.end(), std::ostream_iterator<char>(std::cout, " "));
Note, however, that while these appear the same for the test input, they can behave differently -- the previous version screens out anything but letters (and converts them all to lower case), but this distinguishes upper from lower case, and shows all non-alphabetic characters in the output as well.
char *arr = "saangeetha";
arr is pointing to read only section where string literal saangeetha is stored. So, it cannot be modified and is the reason for access violation error. Instead you need to do -
char arr[] = "sangeetha"; // Now, the string literal can be modified because a copy is made.