Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I have written some code for my own practice purpose, but interesting thing happened. I was originally trying to write a C++ code, however I forgot include streamio library and using namespace std, then I just using printf() function all the way during my coding.
I think the most confusing part to me is I use .cpp extension and compile this program using VS 2015 compiler but I actually wrote in C style. Could someone tell me do I wrote a C or C++ code?
Here is the source code:
#include "stdafx.h"
#include <stdlib.h>
typedef struct node
{
int data;
node *next;
}node;
node *create()
{
int i = 0;
// Each variable must be assign to some value in the function
node *head, *p, *q = NULL;
int x = 0;
head = (node *)malloc(sizeof(node));
while (1)
{
printf("Please input the data: ");
scanf_s("%d", &x);
if (x == 0)
break;
p = (node *)malloc(sizeof(node));
p->data = x;
if (++i == 1) {
head->next = p;
}
else
{
q->next = p;
}
q = p;
}
q->next = NULL;
return head;
}
void printList(node head)
{
node *tmp = &head;
int counter = 0;
printf("Print out the list: \n");
while (tmp->next != NULL) {
tmp = tmp->next;
counter++;
//surprise to me printf() is pretty advance...
printf("%d item in the list: %d\n",counter, tmp->data);
}
}
int main()
{
printList(*create());
return 0;
}
Your code is, as far as I can tell, valid C++. It is not valid C, but could be made valid C with only a little effort.
C is nearly a subset of C++, but there is valid C code that is not valid C++ code -- and of course there's plenty of valid C++ code that's not valid C code.
The one thing that makes your code invalid as C is the use of the name node:
typedef struct node
{
int data;
node *next;
}node;
In C++, the struct node definition makes the type visible either as struct node or as node. In C, the struct definition by itself only creates the name struct node. The name node is not visible until the typedef is complete -- which it isn't at the point where you define node *next;.
If you rename your source file with a .c suffix and compile it as C, the compiler will complain that node is an unknown type name.
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I'm trying to make a linked list from a premade file in c++. I'm struggling with the concept of taking the info if get from the file and using that to make the list. this is what i have so far.I also need to have the ability to insert and delete node from anywhere in the list.
struct node
{
string name;
int id;
float gpa;
node *next;
};
struct node* head;
void insertNodes(short id)
{
struct node* new_node = (struct node*) malloc(sizeof(struct node));
new_node->id = id;
new_node->next = head;
head = new_node;
}
void deleteNode() {
if (head == NULL){
cout << "List is empty" << endl;
return;
}
cout << head->id << " is removed." << endl;
head = head ->next;
}
int main() {
head = NULL;
node entry;
fstream datafile;
datafile.open("datafile.dat", ios::in | ios::binary);
if (!datafile)
{
cout << "Error!!\n";
return 0;
}
datafile.read(reinterpret_cast<char *>(&entry), sizeof(entry));
}
if you are doing this in C++ you shouldn't be using malloc and free generally, and the struct keyword before every instance of the struc; those are C-ism's. You should probably be creating a class of your own to represent the list and using member functions instead of a global variables head, and using new and delete for dynamic instantiation and destruction of variables. There are cases for malloc still but this does not appear to be one them.
additionally your insert function only seems to take an input value and add it to the tail of the list; generally in a list you will want to take the insertion point and value unless you are calling the method 'pushback' or something along those lines.
Further unless you rewrite to make a List class of your own you have not done any object oriented programming currently, as you are just doing things procedurally and the only thing c++ about this code is the use of iostream and fstream.
Suggest that you make node a class as well. it's mostly semantic but will get you in the habit, and give node a constructor even if you don't want to make accessors.
beyond that you are asking for information without having attempted anything and your question is too broad.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I am currently learning c++ and in order to learn it I though I would implement a simple binary search tree class in order to get a hang of the concepts in c++. When implementing an add function I am receiving an interesting error in which it seems that the program does not recognize the node as null then crashes immediately after because the node should be null.
//Here is my add/insert function I created.
void BinarySearchTree::insert(double x){
if(root == NULL){
root = (struct TreeNode*) malloc(sizeof(struct TreeNode));
root->val = x;
return;
}
bool inserted = false;
struct TreeNode* curr = root;
while(curr != NULL && !inserted){
if(curr->val == x){
return;
}
if(x > curr->val){
if(curr->right == NULL){
curr->right = (struct TreeNode*) malloc(sizeof(struct TreeNode));
curr->right->val = x;
inserted = true;
} else {
curr = curr->right;
}
} else {
if(curr->left == NULL){
curr->left = (struct TreeNode*) malloc(sizeof(struct TreeNode));
curr->left->val = x;
inserted = true;
} else {
curr = curr->left;
}
}
}
}
//This is the TreeNode struct and the BinarSearchTree class in my header file if it helps
struct TreeNode{
double val;
struct TreeNode *right;
struct TreeNode *left;
};
class BinarySearchTree{
private:
struct TreeNode *root;
public:
void insert(double x);
};
Grand that you are learning C++!
Have no fear: you only need to wade a little deeper in, to have it all come right. The comments concur that there is a lot yet to learn, but trust us: it will be well worth the effort.
As some comments have indicated, the major issue in this example is that you have not properly initialized the variables you are using in your decision making process, which means that they contain garbage -- any old value whatsoever -- and not the zeroes that you intend them to. Initialization is just as vital in C; C++ only holds your hand more, making sure that you do -- iff you let it.
Indeed, later on you may look into the specialized pointer types that the standard library provides, but at first you may wish to just focus on learning the C++ way of doing things. You may use good 'ol malloc for allocation, but when you do you are actually just making unnecessary work for your self, and at the same time exposing your code to precisely the kind of problem you have encountered. C++ offers you operator new, which will do all the heavy lifting for you, especially when combined with a proper constructor function.
The simple C++ statement:
new TreeNode;
... does more than it appears to. First it allocates the memory required for the object -- most implementations using malloc under the hood. Then it calls the constructor function you have defined for the class, to initialize the data in the structure.
So first, in TreeNode you need something along these lines:
struct TreeNode {
double val;
TreeNode *right;
TreeNode *left;
// default constructor --'ctor'
TreeNode():right(null), left(null) {}
// useful ctor for your particular situation
TreeNode( double val ):TreeNode(), val(val) {}
};
And then, within your ::insert function:
// replace these lines...
if(root == NULL){
root = (struct TreeNode*) malloc(sizeof(struct TreeNode));
root->val = x;
return;
}
// with something like these...
if( !root ) {
root = new TreeNode; // root->val is garbage, for now
return;
}
// and replace the two branch creation sections...
if(curr->right == NULL){
curr->right = (struct TreeNode*) malloc(sizeof(struct TreeNode));
curr->right->val = x;
inserted = true;
}
// ... with something like this
if( !curr->right ) {
curr->right = new TreeNode( x );
break; // you are only setting 'inserted' here to end your loop
}
Constructors -- and the destructors that are their complements -- are powerful tools, and there are many nuances about them for you to discover.
Then, you can get down to the nitty-gritty of streamlining and optimizing your code.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
Here is the Program
#include <iostream>
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
using namespace std;
struct node
{
int data;
node *next;
};
typedef node *list;
bool create(list header){
return header==NULL;
}
void insert_begining(list header,int item){
node*p;
p=new(node);
if (p=NULL)
{
return;
}
p->data=item;
p->next=header;
header=p;
}
void insert_end(list header,int item){
list p,q;
p=new(node);
p->data=item;
p->next=NULL;
if (header==NULL)
{
header=p;
}
else
{
q=header;
while(q->next!=NULL){
q=q->next;
}
q->next=p;
}
}
void print_list(list header){
node* p;
p=header;
while(p->next!=NULL){
cout<<p->data<<endl;
p=p->next;
}
}
int main(){
list header;
create(header);
insert_end(header,500);
insert_end(header,600);
insert_end(header,4);
insert_end(header,6);
print_list(header);
return 0;
}
i run the program and it shows
Process returned -1073741819 (0xC0000005) execution time : 6.720 s
i really don't know why.I think that the syntax is right
pleases check the program above and tell me what to do.
i am a beginner and i really don't know much about linked lists
First, you need to understand pass-by-value vs pass-by-reference. In the former case a copy of the var is passed and in the latter the actual var is passed. Ex:
void f1(int x) { // Pass by value
x = 1;
}
void f2(int& x) { // Pass by reference
x = 2;
}
int main() {
int y = 0;
f1(y);
// y is still 0
f2(y);
// y is now 2
}
In your program, you pass header by value:
void insert_begining(list header,int item){
// ....
header=p; // Only modifying the local var!
}
Some things I would do:
First, get rid of that typedef. This is C++ but you are not using classes, so I assume you haven't learned them yet. Instead, create a linked list struct:
struct node
{
int data;
node *next;
};
struct linked_list {
struct node *head;
linked_list() : head(nullptr) {} // ctor
};
No more typedef needed, and now you can easily pass by reference. Ex:
void insert_begining(linked_list& list, int item){
// removed for brevity
p->next = list.head;
list.head = p;
}
When you declare the header variable it is not initialized to NULL. In C++
variables are usually not initialized by the compiler upon declaration.
So when you make the call
insert_end(header, 500);
inside the function the else block is executed since header is not NULL but a garbage value. The culprit here is:
while(q->next!=NULL);
You cannot evaluate q->next since q points to a random memory location and hence the segfault. You need to assign to a variable before accessing it.
So in you main function add this:
list header = NULL;
Apart for this your might want to check BLUPIX's comments about other problems.
Also use nullptr instead of NULL if the compiler supports C++11
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
Here's my C++ code of a simple structured linklist.
#include <iostream>
using namespace std;
class Node{
public:
int data;
Node* next;
Node* prev;
Node(){
data=-1;
next=NULL;
prev=NULL;
}
Node(int d,Node *nnext){
data=d;
next=nnext;
}
void add(Node* nnext){
next=nnext;
nnext->prev=this;
}
};
void print(Node* head){
Node* cNode;
cNode=head;
while (cNode!=NULL){
cout <<"["<<cNode->data<<"]" << endl;
cNode=cNode->next;
}
}
void insertAfter(Node* pNode, Node* nNode){
nNode->next = pNode->next;
pNode->next = nNode;
pNode->next->prev = nNode;
}
void deleteNode(Node* b){
Node* c=b->next;
Node* a=b->prev;
a->next=c;
c->prev=a;
delete b;
}
void main(){
Node* head;
head=new Node();
head->data=1;
Node * currentNode=head;
for (int i=2;i<=5;i++){
Node* nNode=new Node(i,NULL);
currentNode->add(nNode);
currentNode=nNode;
}
cout << currentNode->data << endl;
print(head);
insertAfter(head, new Node(99,NULL));
//deleteNode(currentNode);
print(head);
}
The case checking is unnecessary because I just need the concept of the linklist. If you have another version of these kind of simple linklist code, please let me know! Thank you!
Your deleteNode() function does not check whether c and a are non-NULL, but immediately dereferences them. This means that your program will crash if you try to delete the first or last node of the list.
Your insertAfter() function also sets pointers in the wrong order, causing nNode->prev to point to itself.
Your deleteNode function is not taking care of the case when you delete the "head" element.
Let's take this list as an example:
head -> n1 -> n2 -> n3 (each of this nodes also has a link to the node before it, just as you did in your code)
If you call deleteNode(head), the following will happen:
Node* c=b->next; // b = head, c = head.next = n1
Node* a=b->prev; // b = head, a = head.prev = NULL
a->next=c; // a = NULL, then NULL->next
You can't access to a variable of a NULL object, that's why you are receiving that runtime error.
P.S: If you want to improve you understanding of data structures I recomend you this book: https://mitpress.mit.edu/books/introduction-algorithms
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
template <class type> class list
{
private:
struct element
{
type data;
element* prev;
element* next;
};
element* begin;
element* end;
int size;
public:
list()
{
begin = NULL;
end = NULL;
size = 0;
}
// data is copied twice. (why? how to solve it?)
void add_at_beginning(type data)
{
element* temp = new element;
temp->next = NULL;
temp->prev = NULL;
temp->data = data;
if (size == 0)
{
begin = end = temp;
size++;
}
else
{
temp->next = begin;
begin->prev = temp;
begin = temp;
size++;
}
}
};
In the function called void add_at_beginning(type data) there is a problem, I wrote the problem in a comment.
Namely I don't understand what it means to say that data is copied twice, and most importantly how can I solve this problem so that nobody says that in this code data is copied twice.
Your function void add_at_beginning(type data) takes its data argument by value, this means that when you call the function, a copy of data is made.
Then when you assign temp->data = data;, a second copy is made.
That's why you've been told that in your code data is copied twice.
You can avoid one of those copies by taking your data argument by reference. This may result in some performance improvements if your class is used with large types.
If you change your function's prototype to :
void add_at_beginning(const type& data)
Then only one copy will be made.