My assignment was to use the reference-based implementation of the ADT List and the array-based implementation of the ADT Stack in a program that has a user enter a string of lower-case letters. I was to go through the string and store each letter in both the list and the stack and then use the stack and list contents to determine if the string is a palindrome or not. I am to display the original sequence of letters, the sequence of letters in reverse order, and finally, a statement whether or not it is a palindrome or not. For some reason, when I input a palindrome, ex. madamimadam, it outputs that it is not a palindrome. I cannot figure out why, please help! Here is my code for the method:
import javax.swing.JOptionPane;
public class PalindromeTester
{
public static void main (String [] args)
{
Character ch;
boolean isPalindrome = true;
LinkedList myList = new LinkedList();
StackArrayBased myStack = new StackArrayBased();
String response = JOptionPane.showInputDialog ("Please enter a string of lower-case letters" ) ;
for ( int i = 0 ; i < response.length ( ) ; i++ )
{
ch = new Character ( response.charAt ( i ) ) ;
myStack.push ( ch ) ;
myList.add ( i + 1 , ch ) ;
}
System.out.println ( "The original sequence of characters is: " + response ) ;
System.out.print ( "The sequence of letters backwards is: " ) ;
int j = 1 ;
while ( ! myStack.isEmpty ( ) )
{
System.out.print ( myStack.peek ( ) ) ;
if ( ! myList.get ( j ).equals( myStack.pop ( ) ) ) ;
isPalindrome = false ;
}
if ( isPalindrome )
System.out.println ( "\nThe string is a palindrome." ) ;
else
System.out.println ( "\nThe string is not a palindrome." ) ;
}
}
Here is the ADT Stack class:
public class StackArrayBased
{
private static final int MAX_STACK = 15 ;
private Object items [ ] ;
private int top ;
public StackArrayBased ( )
{
items = new Object [ MAX_STACK ] ;
top = -1 ;
}
public boolean isEmpty ( )
{
return top < 0 ;
}
public boolean isFull ( )
{
return top == MAX_STACK - 1 ;
}
public void push ( Object newItem ) throws StackException
{
if ( ! isFull ( ) )
items [ ++ top ] = newItem ;
else
throw new StackException ( "StackException on push: stack is full" ) ;
}
public void popAll ( )
{
items = new Object [ MAX_STACK ] ;
top = -1 ;
}
public Object pop ( ) throws StackException
{
if ( ! isEmpty ( ) )
return items [ top -- ] ;
else
throw new StackException ( "StackException on pop: stack is empty" ) ;
}
public Object peek ( ) throws StackException
{
if ( ! isEmpty ( ) )
return items [ top ] ;
else
throw new StackException ( "StackException on peek: stack is empty" ) ;
}
}
and here is the ADT list:
public class LinkedList
{
private Node head;
private int numItems;
public LinkedList ( )
{
head = null ;
numItems = 0 ;
}
public boolean isEmpty ( )
{
return numItems == 0 ;
}
public int size ( )
{
return numItems ;
}
private Node find ( int position )
{
Node curr = head ;
for ( int i = 1 ; i < position ; i ++ )
curr = curr.getNext ( ) ;
return curr ;
}
public Object get ( int position )
{
if ( position >= 0 && position <= numItems )
{
Node curr = find ( position ) ;
Object dataItem = curr.getItem ( ) ;
return dataItem ;
}
else
{
System.out.println ( "Error in position value during get attempt." ) ;
return null ;
}
}
public void add ( int position, Object item )
{
if ( position >= 1 && position <= numItems + 1 )
{
if ( position == 1 )
{
Node newNode = new Node ( item, head ) ;
head = newNode ;
}
else
{
Node prev = find ( position - 1 ) ;
Node newNode = new Node ( item, prev.getNext ( ) ) ;
prev.setNext ( newNode ) ;
}
numItems ++ ;
}
else
System.out.println ( "Position is invalid on attempted add." ) ;
}
public void remove ( int position )
{
if ( position >= 1 && position <= numItems )
{
if ( position == 1 )
head = head.getNext ( ) ;
else
{
Node prev = find ( position - 1 ) ;
Node curr = prev.getNext ( ) ;
prev.setNext ( curr.getNext ( ) ) ;
}
numItems -- ;
}
else
System.out.println ( "Position is invalid on attempted remove." ) ;
}
public void removeAll ( )
{
head = null ;
numItems = 0 ;
}
}
If you want to set isPalindrome correctly, shouldn't you be doing something with j in this loop...?:
[...]
int j = 1 ;
while ( ! myStack.isEmpty ( ) )
{
System.out.print ( myStack.peek ( ) ) ;
if ( ! myList.get ( j ).equals( myStack.pop ( ) ) ) ;
isPalindrome = false ;
}
[...]
In the second loop, you should be incrementing j. Since linkedlist index can be 0, you shouldn't be doing i+1 index while adding ( in the first loop). If you make it a 0 based index you should be initalizing j to be 0 before the second loop.
The assignment seems odd; if you can access the last element of the list (as an abstract list allows in most language), then you can just do the for i=[0,length) {if input[i]!=input[length-1-i], return false} return true
And if you just had stacks to play with, you could just clone and reverse the stack (e.g. by pushing onto two stacks, and popping one of those into a new stack, thereby reversing it), and do the same thing as the for loop (go through the two stacks element-by-element to see if they're the same).
In both of the above linear-time algorithms (either the one that uses just lists, or the one that uses just stacks), the function should just be 3 lines or so.
Related
We have an input string in this format "(1(2(4)(5))(3(6(8)(9))(7)))"
We have to build a Binary Tree such that 1 is the root node and the first complete bracket contains (2(4)(5)) contains the family of 1's left child
and (3(6(8)(9))(7)) is the family of the right child of the root A.
Finally the tree will look like this.
Like this
I am not able to find the exact algorithm to write convert this one. Thanks in Advance!
Think Stack.
When you see a "(" push the element onto the stack, when you see a ")" pop the stack, but assign it as a child to the top element of the stack.
So lets go through the example "( 1 ( 2 ( 4 ) ( 5 ) ) ( 3 ( 6 ( 8 ) ( 9 ) ) ( 7 ) ) )"
(1 -> push 1
(2 -> push 2
(4 -> push 4
) -> pop 4, but assign 4 as child to top of stack which is 2 ( see if left is available then assign as left child otherwise right child )
Current tree :
(5 -> push 5
) -> pop 5, top of the stack is still 2 ( left is not available so assign it as right child of 2 )
Current tree:
) -> pop 2, top of the stack is 1 ( left of 1 is available, so assign 2 as left child of 1)
Current tree:
(3 -> push 3
(6 -> push 6
(8 -> push 8
) -> pop 8, top of the stack 6's left is available assign 8 as left of 6
Current tree:
(9 -> push 9
) -> pop 9 -> add it to top of stack's right child i.e. 6's right child because 6's left is taken as 8.
Current tree:
) -> pop 6 -> add it to top of stack i.e. 3's left child as it is available.
Current tree:
(7 -> push 7
) -> pop 7 -> add it to top of stack i.e. 3's right child because 3's left child is taken as 6.
) -> pop 3 -> add it to top of stack i.e. 1's right child because 1's left child is taken as 2.
Current tree:
) -> pop 1 -> there is nothing in the stack now. Done.
Complete runnable example in Java with implementation using a stack is:
import java.util.*;
public class Main
{
public static void main(String[] args) {
TreeNode root = buildTree("(1(2(4)(5))(3(6(8)(9))(7)))");
levelOrder(root);
}
static class TreeNode {
int val;
TreeNode left, right;
public TreeNode(int val) {
this.val = val;
}
}
private static TreeNode buildTree(String s) {
Deque<TreeNode> dq = new ArrayDeque<>();
TreeNode rootNode = null;
for ( int i = 0; i < s.length(); i++ ) {
if ( s.charAt(i) == '(' ) {
Integer current = Integer.parseInt(String.valueOf(s.charAt(i+1)));
dq.push(new TreeNode(current));
} else if ( s.charAt(i) == ')' ) {
TreeNode node = dq.pop();
if ( dq.isEmpty() ) {
break;
} else {
rootNode = dq.peek();
if (rootNode.left == null) {
rootNode.left = node;
} else {
rootNode.right = node;
}
}
}
}
return rootNode;
}
private static void levelOrder(TreeNode root) {
Deque<TreeNode> dq = new ArrayDeque<>();
dq.offer(root);
while(!dq.isEmpty()) {
int sz = dq.size();
for ( int i = 0; i < sz; i++ ) {
TreeNode node = dq.poll();
System.out.print(node.val + " ");
if ( node.left != null ) {
dq.offer(node.left);
}
if ( node.right != null ) {
dq.offer(node.right);
}
}
System.out.println();
}
}
}
Of course, I can't just write the code for your assignment here :-) but I think it may help if you think on each symbol as an operation, for example
( = down
1 = add
( = down
2 = add
( = down
4 = add
) = up (goes to level of 2)
( = down
5 = add
) = up (goes to level of 2)
) = up (goes to level of 1)
( = down
3 = add
( = down
6 = add
( = down
8 = add
) = up (goes to level of 6)
( = down
9 = add
) = up (goes to level of 6)
) = up (goes to level of 3)
( = down
7 = add
) = up (goes to level of 3)
) = up (goes to level of 1)
) = up (leaves)
If you think in terms of a recursive algorithm, you may think of "going down" as a recursive method call and "going up" as returning from the recursive method call (which happens automatically, then the method itself completes).
I strongly suggest you to try to solve the problem because it's really important to learn.
However, if you still can't find the solution, you may find some detailed explanation here on how to solve it. https://www.geeksforgeeks.org/construct-binary-tree-string-bracket-representation/
The string lists the nodes in preorder sequence. So a recursive solution would be a possible choice.
In JavaScript you'd write it as follows:
class Node {
constructor(value) {
this.value = value;
this.children = [];
}
}
function createTree(str) {
// Extract numbers and parentheses from input into an array
let tokens = str.match(/\d+|./g);
if (!tokens) return null;
let i = 1; // skip first character, as it must be a "("
function recur() {
let node = new Node(tokens[i++]);
while (tokens[i++] != ")") {
node.children.push(recur());
}
return node;
}
return recur();
}
// Demo run
let str = "(1(2(4)(5))(3(6(8)(9))(7)))";
let tree = createTree(str);
// Output the tree in JSON format
console.log(JSON.stringify(tree, null, 2));
Note that this implementation does not perform any validation of the input. It is assumed that the input has a correct syntax.
The algorithm will accept encodings of non-binary trees, as this format may encode nodes that have any number of children.
This code is made for the multiplication of two arrays given by the user
typedef vector<vector<int> > arr ;
void multiply (arr &arr1 ,arr &arr2 )
{
arr res ;
unsigned new_row = arr1.size() ;
unsigned new_col = arr2.at(0).size();
for(int i = 0 ; i < new_row ; i++)
{
vector <int> vec ;
res.push_back(vec ) ;
for(int j = 0 ; j<new_col ;j++)
{
int x = 0 ;
res.at(i).push_back(x);
for(unsigned k =0 ; k <arr2.size();k++)
{
res.at(i).at(j) += arr1.at(i).at(k)*arr2.at(k).at(j);
}
cout<< res.at(i).at(j) ;
}
}
}
int main()
{
unsigned rows_number1 = 0 , columns_number1 = 0 ;
arr arr1 ;
cout<<"MATRIX A "<<endl<<endl ;
cout << "The Rows : " ;
cin >> rows_number1 ;
cout << "The Columns :" ;
cin>> columns_number1 ;
for(int i = 0 ; i<rows_number1;i++)
{
vector<int> newr ;
arr1.push_back(newr);
for(int j = 0; j<columns_number1 ;j++)
{
int x ;
cout<<"The Member ("<<i+1<<","<<j+1 <<") :" ;
cin>>x ;
arr1.at(i).push_back(x);
}
}
unsigned rows_number2 = 0 , columns_number2 = 0 ;
arr arr2 ;
cout<<"MATRIX B "<<endl<<endl ;
cout << "The Rows : " ;
cin >> rows_number2 ;
cout << "The Columns :" ;
cin>> columns_number2 ;
for(int i = 0 ; i<rows_number2;i++)
{
vector<int> newr ;
arr1.push_back(newr);
for(int j = 0; j<columns_number2 ;j++)
{
int x ;
cout<<"The Member ("<<i+1<<","<<j+1 <<") :" ;
cin>>x ;
arr1.at(i).push_back(x);
}
}
system("cls");
if(columns_number1!=rows_number2)
{
cout<<"Error Multiplication Dimensions" <<endl ;
}
else
{
cout << "A * B ="<<endl;
multiply(arr1,arr2);
}
}
why there is an error and what is the other way ??
how i can improve the code to multiplicate two arrays
Edited : i tried with two 2*2 arrays using console input and output and this is my full code
The problem is out_of_range exception but i don't know why
When you mulitply to matrices, there are strict constraints on the input.
The number of columns of the first matrix must be the same as the number of rows of the second matrix.
When your matrix is represented by a std::vector<std::vector<int>>, you'll have to make sure that ALL the nested std::vectors are of the same size.
Also, don't assume that arr2 is non-empty. When it is empty, arr2.at(0) will thrown an exception.
Here's a more robust version of your function.
void multiply (arr &arr1 ,arr &arr2 )
{
arr res;
unsigned num_rows1 = arr1.size();
if ( num_rows1 == 0 )
{
// Can't do much.
// Return.
return res;
}
unsigned num_cols1 = arr1[0].size();
if ( num_cols1 == 0 )
{
// Can't do much.
// Return.
return res;
}
// Inner vector size check of arr1.
for(unsigned int i = 1 ; i < num_rows1 ; i++)
{
if ( num_cols1 != arr1[i].size() )
{
throw std::runtime_error("Bad input");
}
}
// Make sure the number of columns in arr1 is the same as
// number of rows in arr2.
unsigned num_rows2 = arr2.size();
if ( num_cols1 != num_rows2 )
{
throw std::runtime_error("Bad input");
}
unsigned num_cols2 = arr2[0].size();
if ( num_cols2 == 0 )
{
// Can't do much.
// Return.
return res;
}
// Inner vector size check of arr2.
for(unsigned int i = 1 ; i < num_rows2 ; i++)
{
if ( num_cols2 != arr2[i].size() )
{
throw std::runtime_error("Bad input");
}
}
// All inputs appear to be valid.
// Now, do the multiplication.
unsigned new_row = num_rows1;
unsigned new_col = num_cols2;
res.resize(num_rows1);
for(unsigned i = 0 ; i < new_row ; i++)
{
for(unsigned j = 0 ; j<new_col ;j++)
{
int x = 0 ;
res.at(i).push_back(x);
for(unsigned k =0 ; k < num_cols1; k++)
{
res.at(i).at(j) += arr1.at(i).at(k)*arr2.at(k).at(j);
}
cout<< res.at(i).at(j) ;
}
}
}
User enters a sentence and a word which he wants to search both. Now we need to find whether word is there or not . without using string functions
You can develop your own function if you dont want to to use string functions,
for example the function you want would be similar to this one:
bool find( char * str, char * word )
{
int i,j,k,l;
i = strlen( str );
k = strlen( word );
l = 0;
while ( i >= k )
{
j = 0;
while ( *(str+j+l) == *(word+j) )
{
j++;
}
i--; l++;
if ( j >= k )
{
return true;
}
}
return false;
}
In above example 'str' would be the string in which you want to search and 'word' would the string you want to search.
I modified the code to work with two files. to_search.txt has string to be searched. big_file.fastq has lines where to be searched and if string found (2 mismatch allowed with exact length which range from 8-10, no addition and deletion), place in respective name. So each string is searched in all lines (2nd line) in big_file.fastq.
# to_search.txt: (length can be from 8-20 characters)
1 TCCCTTGT
2 ACGAGACT
3 GCTGTACG
4 ATCACCAG
5 TGGTCAAC
6 ATCGCACA
7 GTCGTGTA
8 AGCGGAGG
9 ATCCTTTG
10 TACAGCGC
#2000 search needed
# big_file.fastq: 2 billions lines (each 4 lines are associated: string search is in second line of each 4 lines).
# Second line can have 100-200 characters
#M04398:19:000000000-APDK3:1:1101:21860:1000 1:N:0:1
TCttTTGTGATCGATCGATCGATCGATCGGTCGTGTAGCCTCCAACCAAGCACCCCATCTGTTCCAAATCTTCTCCCACTGCTACTTGAAGACGCTGAAGTTGAAGGGCCACCTTCATCATTCTGG
+
#8ACCDGGGGGGGGGGGGGEGGGGGGGGDFFEGGG#FFGGGGGGGGGGGGGGGGGCF#<FFGGGGGFE9FGGGFEACE8EFFFGGGGGF9F?CECEFEG,CFGF,CF#CCC?BFFG<,9<9AEFG,,
#M04398:19:000000000-APDK3:1:1101:13382:1000 1:N:0:1
NTCGATCGATCGATCGATCGATCGATCGTTCTGAGAGGTACCAACCAAGCACACCACGGGCGACACAGACAGCTCCGTGTTGAACGGGTTGTTCTTCTTCTTGCCTTCATCATCCCCATCCTCAGTGGACGCAGCTTGCTCATCCTTCCTC
+
#8BCCGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
#M04398:19:000000000-APDK3:1:1101:18888:1000 1:N:0:1
NCAGAATGAGGAAGGATGAGCCCCGTCGTGTCGAAGCTATTGACACAGCGCTATTCCGTCTTTATGTTCACTTTAAGCGGTACAAGGAGCTGCTTGTTCTGATTCAGGAACCGAACCCTGGTGGTGTGCTTGGTTGGCAAGTTTACGGCTC
+
#8BCCGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGCGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGFGGGGGGGGGGGGGGGGGGGGGGGGGGGE
Here is the code for two mismatches. I tried with exact match, speed is not bad: takes around a day. I have used Time::Progress module. When I use 2 mismatch: shows 115 days to finish. How the speed can be improved here?
#!/usr/bin/perl
use strict;
use warnings;
$| = 1;
open( IN_P1, "big_file.fastq" ) or die "File not found";
my ( #sample_file_names, #barcode1 );
open( BC_FILE, "to_search.txt" ) or die "No barcode file";
my #barcode_file_content = <BC_FILE>;
foreach (#barcode_file_content) {
chomp $_;
$_ =~ s/\r//;
$_ =~ s/\n//;
#print $_;
my #elements = split( "(\t|,| )", $_ );
push #sample_file_names, $elements[0];
push #barcode1, $elements[2];
}
# open FH
my #fh_array_R1;
foreach (#sample_file_names) {
chomp $_;
local *OUT_R1;
open( OUT_R1, ">", "$_\.fq" ) or die "cannot write file";
push #fh_array_R1, *OUT_R1;
}
# unknown barcode file
open( UNKNOWN_R1, ">unknown-barcode_SE.fq" ) or die "cannot create unknown-r1 file";
while ( defined( my $firstp1 = <IN_P1> ) ) {
my $p1_first_line = $firstp1;
my $p1_second_line = <IN_P1>;
my $p1_third_line = <IN_P1>;
my $p1_fourth_line = <IN_P1>;
chomp( $p1_first_line, $p1_second_line, $p1_third_line, $p1_fourth_line, );
my $matched_R1 = "$p1_first_line\n$p1_second_line\n$p1_third_line\n$p1_fourth_line\n";
for ( my $j = 0 ; $j < scalar #barcode1 ; $j++ ) {
chomp $barcode1[$j];
my $barcode1_regex = make_barcode_fragments( $barcode1[$j] );
if ( $p1_second_line =~ /$barcode1_regex/i ) {
# keep if matched
print { $fh_array_R1[$j] } $matched_R1;
last;
}
else {
#print to unknown;
print UNKNOWN_R1 $matched_R1;
}
}
}
# make two mismatch patterm of barcode
sub make_barcode_fragments {
my ($in1) = #_;
my #subpats;
for my $i ( 0 .. length($in1) - 1 ) {
for my $j ( $i + 1 .. length($in1) - 1 ) {
my $subpat = join( '',
substr( $in1, 0, $i ),
'\\w', substr( $in1, $i + 1, $j - $i - 1 ),
'\\w', substr( $in1, $j + 1 ),
);
push #subpats, $subpat;
}
}
my $pat = join( '|', #subpats );
#print $pat;
return "$pat";
}
exit;
If your algorithm cannot be changed/improved in Perl itself, you can still get speedup by writing the time consuming parts in C. Here is an example using inline C:
use strict;
use warnings;
use Benchmark qw(timethese);
use Inline C => './check_line_c.c';
my $find = "MATCH1";
my $search = "saasdadadadadasd";
my %sub_info = (
c => sub { check_line_c( $find, $search ) },
perl => sub { check_line_perl( $find, $search ) },
);
timethese( 4_000_000, \%sub_info );
sub check_line_perl {
my ($find, $search ) = #_;
my $max_distance = 2;
for my $offset ( 0 .. length($search) - length($find) ) {
my $substr = substr( $search, $offset, length($find) );
my $hd = hd( $find, $substr );
if ( $hd <= $max_distance ) {
return ( $hd, $substr );
}
}
return ( undef, undef );
}
sub hd {
return ( $_[0] ^ $_[1] ) =~ tr/\001-\377//;
}
where check_line_c.c is:
void check_line_c( char* find, char * search ) {
int max_distance = 2;
int flen = strlen(find);
int last_ind = strlen(search) - flen;
SV *dis = &PL_sv_undef;
SV *match = &PL_sv_undef;
for ( int ind = 0; ind <= last_ind; ind++ )
{
int count = 0;
for ( int j = 0; j < flen; j++ )
{
if ( find[j] ^ search[ind+j] ) count++;
}
if ( count < max_distance )
{
match = newSV(flen);
sv_catpvn(match, search+ind, flen );
dis = newSViv(count);
break;
}
}
Inline_Stack_Vars;
Inline_Stack_Reset;
Inline_Stack_Push(sv_2mortal(dis));
Inline_Stack_Push(sv_2mortal(match));
Inline_Stack_Done;
}
The output is (Ubuntu Laptop using Intel Core i7-4702MQ CPU #2.20GHz):
Benchmark: timing 4000000 iterations of c, perl...
c: 2 wallclock secs ( 0.76 usr + 0.00 sys = 0.76 CPU) # 5263157.89/s (n=4000000)
perl: 19 wallclock secs (18.30 usr + 0.00 sys = 18.30 CPU) # 218579.23/s (n=4000000)
So this gives a 24-fold speedup for this case.
I'd suggest creating a really bad hashing algorithm. Something nice and reversible and inefficient, like the sum of the characters. Or maybe the sum of unique values (1-4) represented by the characters.
Compute the target sums, and also compute the maximum allowed variance. That is, if the objective is a match with two substitutions, then what is the maximum possible difference? (4-1 + 4-1 = 6).
Then, for each "window" of text of the appropriate length in the target data file, compute a running score. (Add a character to the end, drop a character from the start, update the hash score.) If the score for a window is within the allowable range, you can do further investigation.
You might want to implement this as different passes. Possibly even as different stages in a shell pipeline or script. The idea being that you might be able to parallelize parts of the search. (For instance, all the match strings with the same length could be searched by one process, since the hash windows are the same.)
Also, of course, it is beneficial that you can keep your early work if your program crashes in the later stages. And you can even have the early parts of the process running while you are still developing the end stages.
So, I have been doing this question :
Q. Write a program that lets users keep track of the last time they talked to each of their friends. Users should be able to add new friends (as many as they want!) and store the number of days ago that they last talked to each friend. Let users update this value as well.
I have created pointer to pointer user_friends to store the 2D string array for names of friends and no. of days since last talked. It's a 3x2 array initially for 3 friends. The 2 columns store friend's name and no. of days ( both in string type pointer array ).
My main has this :
int tsize = 3;
string **user_friends = new string*[tsize];
for ( int i = 0; i < tsize; i++ )
{
user_friends[i] = new string[2];
}
Here is the addFriends function to add friends in array.
void addFriends( string **user_f , int tsize )
{
static int next_friend = 0;
int index = 0;
string days;
if ( next_friend >= tsize )
{
cout << "\nGrowing array now...";
user_f = growArray ( user_f, tsize );
}
cout << "\n\nEnter index : ";
cin >> index;
cin.ignore();
cout << "\nEnter friend's name : ";
getline( cin, user_f[index][0] );
cout << "\nEnter days since last talked with this friend : ";
getline (cin, days);
user_f[index][1] = days;
next_friend++;
}
Then there is this growArray function to expand the memory allocated to string array :
string **growArray ( string **ptr, int cur_size )
{
string **new_ptr = new string*[ cur_size*2 ];
for ( int i = 0; i < cur_size; ++i )
{
new_ptr[i] = new string[2];
}
for( int i = 0; i < cur_size; ++i )
{
new_ptr[i] = ptr[i];
}
for ( int i = 0; i < cur_size; ++i )
{
for ( int j = 0; j < 2; ++j)
{
new_ptr[i][j] = ptr[i][j];
}
}
for ( int i = 0; i < cur_size; ++i )
{
delete ptr[i];
}
delete[] ptr;
return new_ptr;
}
Then this display function to print the array.
void displayFriends( string **user_f, int tsize )
{
for ( int i = 0; i < tsize; ++i )
{
for( int j = 0; j < 2; ++j )
{
cout << user_f[i][j] << "\t";
}
cout << endl;
}
}
Now, when I have entered upto 3 friends details, the program runs fine.
When I start to enter the details of friend 4 ( i.e. When I type in index as 3 ) the program crashes. Is there any problem with the growArray function ?
Also, is the display function alright ?
In the growArray function the first for loop should iterate from 0 to 2 * cur_size instead of 0 to cur_size.
for(int i = 0; i< 2 * cur_size; i++)
new_ptr[i] = new string[2]