C++ Reversal string using pointers - c++

I have been given the task to receive a string input from the user and reverse the order of the string and print the result out. My code is this:
#include <iostream>
#include <cstring>
#include <string>
using namespace std;
int main() {
string input;
char *head = new char, *tail = new char;
char temp;
//Get the string from the user that will be reversed
cout << "Enter in a string that you want reversed: ";
getline(cin, input);
//Create and copy the string into a character array
char arr[input.length()];
strcpy(arr, input.c_str());
//Set the points of head/tail to the front/back of array, respectably
head = &arr[0]; tail = &arr[input.length()-1];
//Actual reversal part of the code (Does not work)
for(int i=0; i<input.length(); i++) {
temp = *(tail);
*tail = *head;
*head = temp;
tail --; head ++;
}
//Print the character array
for(int i=0; i<input.length(); i++) {
cout << arr[i];
}
//Free up memory
delete head; delete tail;
head = NULL; tail = NULL;
return 0;
}
When I print it, literally nothing has been changed and I can't seem to understand why as I'm brand new to pointers. This is the specific block that I'm having trouble with:
for(int i=0; i<input.length(); i++) {
temp = *(tail);
*tail = *head;
*head = temp;
tail --; head ++;
}
Any input on how to fix this or pointer knowledge in general that'd help is greatly appreciated.

Your approach is good but...
for(int i=0; i<input.length(); i++) {
temp = *(tail);
*tail = *head;
*head = temp;
tail --; head ++;
}
Didn't you try working this out on paper? You swap each pair of letters twice, bringing the array back to its original order.
Just change the limit of iteration, to stop when head and tail meet in the middle, and you'll be all right:
for(int i=0; i<input.length()/2; i++) {
...
}

Related

Why am I getting extra output for linked list

The question is
There is a collection of input strings and a collection of query strings. For each query string, determine how many times it occurs in the list of input strings.
strings = [ab,ab,abc]
queries = [ab,abc,bc]
There are instances 2 of ab, 1 of 'abc' and 0 of 'bc'. For each query, add an element.
#include <iostream>
#include <cstdio>
#include <string>
using namespace std;
struct node {
int data;
node *next;
}*first=NULL,*last= new node;
void create(int count) {
node *temp;
temp = new node;
temp->data = count;
temp->next = NULL;
if(!first) first=last=temp;
else {
last->next = temp;
last = temp;
}
}
void display() {
node *temp = first;
while(temp) {
cout<<temp->data<<endl;
temp = temp->next;
}
}
void matchStrings(string s[],string q[],int s_count,int q_count){
int counter;
// res = new int[q_count];
for(int i=0;i<=q_count;i++){
counter = 0;
for(int j=0;j<s_count;j++){
if( q[i] == s[j] ) counter++;
}
if(counter != 0) create(counter);
else create(0);
}
// return res;
}
int main() {
int string_count,query_count,*res;
cin>>string_count;
string strings[string_count];
for(int i=0;i<string_count;i++) cin>>strings[i];
cin>>query_count;
string queries[query_count];
for(int i=0;i<query_count;i++) cin>>queries[i];
matchStrings(strings,queries,string_count,query_count);
// res = matchStrings(strings,queries,string_count,query_count);
matchStrings(strings,queries,string_count,query_count);
// for(int i=0;i<query_count;i++) cout<<res[i]<<endl;
display();
return 0;
}
Now I am trying to implement it using Linked List but instead of getting output as 2,1,0.
I am getting output as 2,1,0,2,2,1,0,2.
I dont how is the LL being created for more than 3 links.
Please help.
In the function void matchStrings(),
you have written
for(int i=0;i<=q_count;i++){
Rather it should be
for(int i=0;i<q_count;i++){
Because of the extra iteration, a randomly generated string gets checked with the set of strings[], and as a result they are incorrectly matched.
So this leads to the execution of create(0) one extra time, which results in creating an extra node with data 0, that gets printed.

Creating and printing linked list from user input C++

#include <iostream>
using namespace std;
int main()
{
struct node
{
int data;
node * next;
};
node * head;
node * n;
node * temp;
node * q;
int number;
cout << "Enter numbers";
cin >> number;
n = new node;
n->data = number;
head = n;
temp = n;
while (cin >> number)
{
while (number != -500)
{
n = new node;
n->data = number;
temp->next = n;
temp = n;
}
}
while (head != NULL)
{
cout << head->data;
head = head->next;
}
}
I don't understand why this would not work. The program creates a new node then sets whatever the user entered equivalent to the variable data of that new node then it makes head and temp point to the new node. Then it gets the users second input and compares it to -500 and if it evaluates as true it creates a new node puts the data of the second input into the variable data then it links the first node and second node together then it makes temp point to the second node. If the condition of the 2nd while loop is false it goes to the third which is where it is suppose to print the list.
Who sets the last node's next to NULL?
At n = new node; n->next is not NULL but undefined, in Debug versions usually it is 0xcccccccc or something similar value to make it visible that it is not initialized. If you try to dereference it, you will get an access violation.
while (cin >> number) { // this loop is endless, because you can always read the user input data (unless some exception happen)
while (number != -500)
{
n = new node; // you already have data allocated. no need to allocate it once more
n->data = number;
temp->next = n;
temp = n;
// as was already mentioned: set n->next to NULL
} }
if you want to break after you checked that the number is not -500, then you can do the following instead:
while (cin >> number) {
if (number != -500) { ...; // do your stuff
break;
}
}
And, by the way, you have a memory leak. If you use flat C pointers then consider delete operator to clear your memory. For that purpose, you need to know where your list starts(basically, head) and iterate through a whole list invoking delete node.
Please, also consider, that it is a bad code style to write something like:
while (cin >> number)
You can also try this-
This code makes a linked list on user input and printlinkedlist (function) print the linked list created.
#include <bits/stdc++.h>
using namespace std;
struct node
{
int data;
node* next;
};
void printlinkedlist(node* node)
{
int c=0; //taken just for good looking output
while(node!=NULL)
{
if(c>0)
{
cout<<"->"<<node->data;
node = node->next;
}
else
{
cout<<node->data;
node = node->next;
c++;
}
}
}
int main() {
int n;
cout<<"Enter no. of nodes=";
cin>>n; //User enters number of nodes he want.
int num,c=0; //initialized c for setting head with second node..
node* head = new node; //initialized head node
node * temp = new node; //initialized temp node
cin>>num;
head->data=num;
for(int i=2;i<=n;i++)
{
if(c==0)
{
cin>>num;
temp->data=num;
head->next=temp; //head point to second node i.e. temp
c++;
}
else
{
cin>>num;
node * temp1 = new node; //initialize other temp node for every value
temp1->data=num;
temp->next=temp1; //point to temp1 to temp
temp=temp1; //set temp as temp1
}
}
printlinkedlist(head);
}
#include<iostream>
using namespace std;
class node{
public:
int data;
node* next;
};
// a function to create linked list passing pointer to pinter
void create_list(node**head)
{
int num;//num is the data
cin>>num ;
node*new_node=new node();//
new_node->data=num;
new_node->next=NULL;
node*temp;
if(*head==NULL)
{
*head=temp=new_node;
}
else{
temp->next=new_node;
temp=new_node;
}
}
void print_list(node* head)
{
if(head == NULL)
{
cout<<"empty list"<<endl;
}
node *ptr = NULL;
ptr=head;
cout<<"data in the list: "<<endl;
while(ptr!=0)
{
cout<<ptr->data<<endl;
ptr=ptr->next;
}
}
int main()
{
int n,i; //
cout<<"enter the number of nodes:"<<endl;
cin>>n;
cout<<"enter data as num:"<<endl;
node* head=NULL;
for(i=0;i<n;i++)
{
create_list(&head);//passing the address of head
}
print_list(head);
return 0;
}

Linked list not printed

I have written a code that creates a linked list of the size, specified by user and prints it. But I have noticed some strange behavior:
if I implement this algorithm it does print a list properly:
struct num
{ int l;
num* p_next; };
void add (int size, num* head) {
srand (time(0));
for (int i = 0; i< size; i++) {
num* newnode = new num;
newnode->l = rand()%100;
newnode->p_next = head;
head = newnode;}
while (head != 0) {
cout << head->l << endl;
head = head -> p_next;}
}
int main () {
num* head = 0;
add (10, head);
}
But when I want to make a code supposedly more safe by eliminating a memory leak and write the same task as:
struct num
{ int l;
num* p_next; };
void add (int size, num* head) {
srand (time(0));
for (int i = 0; i< size; i++) {
num* newnode = new num;
newnode->l = rand()%100;
newnode->p_next = head;
head = newnode;}
}
int extract (num*head) {
int n;
n = head->l;
head = head->p_next;
delete head;
return n;}
void print (num *head) {
while (head != 0) {
cout << extract (head) << endl;
}}
int main () {
num* head = 0;
add (10, head);
print (head);
cin.get();
cin.ignore();
}
..it does not print anything. I feel that the problem lies in something very small, but I cannot find it. Why it does not print it in second case?
Your problem is that head is passed by value (yes, pointers can be passed by value) to add instead of by reference. When you call print, your head is not the front of the list (because it wasn't actually modified in add, only a copy of it was.)
Try this:
void add (int size, num*& head)
{
srand (time(0)); //actually move this line to main, don't do it here
for (int i = 0; i< size; i++)
{
num* newnode = new num;
newnode->l = rand()%100;
newnode->p_next = head;
head = newnode;
}
}
You have a similar problem with extract and print
Edit: Your extract function also improperly deletes memory. Here's a full working example:
#include <iostream>
#include <ctime>
using namespace std;
struct num
{
int l=0;
num* p_next=nullptr;
};
void add (int size, num*& head)
{
for (int i = 0; i<size; i++)
{
num* newnode = new num;
newnode->l = rand()%100;
newnode->p_next = head;
head = newnode;
}
}
int extract (num*& head)
{
int n;
n = head->l;
num* tmp = head;
head = head->p_next;
delete tmp;
return n;
}
void print (num*& head)
{
while (head != nullptr)
cout << extract(head) << endl;
}
int main ()
{
srand (time(0));
num* head = nullptr;
add (10, head);
print (head);
}
Live Demo
You need a temporary node. You need to set the temp to the next node from the head and then delete head. Then you set head to the temp node.
int extract (num*head)
{
int n;
n = head->l;
num* temp = head->p_next
delete head;
head = temp;
return n;
}

Deallocating Dynamic Memory

I recently did a school homework assignment and lost points, in the comment the grader said that I didn't deallocate the pointers correctly.
Below is the code I sent, I would just like to know how it would look to deallocate the pointers correctly?
/*Student: Daniel
*Purpose: To reverse a string input using
*pointers.
*/
#include <iostream>
#include <cstring>
#include <string>
using namespace std;
int main() {
string input;
char *head = new char, *tail = new char;
char temp;
//Get the string from the user that will be reversed
cout << "Enter in a string that you want reversed: ";
getline(cin, input);
//Create and copy the string into a character array
char arr[input.length()];
strcpy(arr, input.c_str());
//Set the points of head/tail to the front/back of array, respectably
head = &arr[0]; tail = &arr[input.length()-1];
for(int i=0; i<input.length()/2; i++) {
temp = *(tail);
*tail = *head;
*head = temp;
tail --; head ++;
}
for(int i=0; i<input.length(); i++) {
cout << arr[i];
}
//********MY PROBLEM AREA*************
delete head; delete tail;
head = NULL; tail = NULL;
return 0;
}
So take a look here...
char *head = new char, *tail = new char;
And then...
//Set the points of head/tail to the front/back of array, respectably
head = &arr[0]; tail = &arr[input.length()-1];
You reassigned what head and tailpoint to, so you're not actually deleting the right things when you call delete. In fact, I'm surprised you don't crash.
Really you can probably just do:
char *head = NULL; char* tail = NULL;
and then not delete anything since you won't have anything dynamic.

Inserting an integer at the end of the list and deleting at nth position

So, in my linked list program, what I want it to do is to ask the user how many numbers to input, and enter the numbers, and add those numbers at the end of the list. Then, it will print the list. After that, the user will choose a position of element in the list to delete and the list will be printed again.
#include <iostream>
using namespace std;
struct Node{
int data;
Node* link;
};
Node* head;
void Insert(int data){ //insert an integer at the end of the list
Node* temp = new Node();
Node* temp2 = new Node();
temp->data = data;
temp->link = NULL;
if(head = NULL){
head = temp;
return;
}
temp2 = head;
while(temp2->link != NULL){
temp2 = temp2->link;
}
temp2->link = temp;
}
void Delete(int n){ //delete an integer at nth position
Node* temp1 = new Node();
temp1 = head;
if(n == 1){ //if the first node is to be deleted
head = temp1->link; //now head points to second node
delete temp1; //delete first node
return;
}
for(int i = 0; i < n-2; i++){
temp1 = temp1->link; //temp1 points to (n-1)th node
}
Node* temp2 = temp1->link; //temp2 points to nth node
temp1->link = temp2->link; // pointing to (n+1)th node
delete temp2; //deleting nth node
}
void Print(){ //print out the list
Node* printNode = head;
cout << "List: ";
while(printNode != NULL){
cout << printNode->data;
cout << " ";
printNode = printNode->link;
}
cout << "\n";
}
int main(){
int x, count, n;
head = NULL; //start with an empty list
cout << "How many numbers? " << endl;
cin >> count;
for(int i = 0; i < count; i++){
cout << "Enter number: ";
cin >> x;
Insert(x);
}
Print();
cout << "Enter position to delete: ";
cin >> n;
Delete(n);
Print();
return 0;
}
After accepting the first number, the program stops working. Can I know where I did the code wrong and what can I do to make this code more efficient? Thanks in advance.
Big facepalm on my part, only a small mistake. Code has been corrected.
if(head == NULL){
head = temp;
return;
}
You might need to rethink your insertion function. The part that your code crashes on is during the while loop insertion. If you want temp2 to hold data then you need to dynamically allocate space for it which you did. However, you are just using it as a position indicator (to traverse the list) - so why do you need to allocate space just to point to head or any other nodes location in your list?
Here's how I would insert into the list (at the back of course):
void Insert(int data){ //insert an integer at the end of the list
Node* temp = new Node();
// This is to ensure that temp was created -> Also called defensive programming.
if (!temp)
{
cout << "We did not have enough space alloted to dynamically allocate a node!" << endl;
exit(1);
}
temp->data = data; // Bad nominclature for program; Don't use the same name twice.
temp->link = NULL;
if (head == NULL)
{
head = temp;
}
else
{
// This is to help traverse the linked list without having to
// manipulate the position of what head points to.
Node *Pos_Indicator = head;
while (Pos_Indicator->link != NULL)
{
Pos_Indicator = Pos_Indicator->link;
}
// We are at the end of the list, it is now safe to add.
Pos_Indicator->link = temp;
// Should probably have a check here for whether it was successful or not.
}
}
I was able to compile and run your code to completion with no other problems. Let me know if this helps!
EDIT: or you know (head = NULL) to (head == NULL) works too :(