Archiwa tagu: cpp

Przekazywanie parametrów do funkcji w C++. Ściągawka

Kontynuując temat z poprzedniego wpisu, Wskaźniki w C++, referencje. Ściągawka, dziś ciąg dalszy. Jak wygląda przekazywanie parametrów do funkcji w C++? Jak przekazać wartości do funkcji, aby można było zmodyfikować wartość parametru?

Pierwsze, co przychodzi do głowy to coś takiego – zwykłe przekazanie parametru jako wartość:

Przekazywanie parametrów przez wartość

Co tu się jednak stało? Czytaj dalej

Wskaźniki w C++, referencje. Ściągawka

Wskaźniki w C++ są chyba najbardziej problematycznym elementem tego języka dla początkujących programistów. Przygotowałam krótką ściągawkę z najważniejszymi informacjami na temat wskaźników, referencji i klas w C++.

Wskaźniki w C

Wskaźnik. Foto: moje, marzec 2018

Czym są wskaźniki w C++?

Wskaźnik – zmienna, której wartością jest adres w pamięci. Można mu przypisać wskazanie na adres w pamięci – wtedy wskaźnik „wskazuje” na tą pamięć.

W pracy ze wskaźnikami potrzebne są dwa operatory:

  • * – operator wyłuskania, pobrania wartości wskaźnika
  • & – operator pobrania adresu.

Zobaczmy w poniższym kodzie, co jest wypisane w przypadku próby wypisania wartości wskaźników i zmiennych. Wartość wskaźnika można zmieniać, co również widać w poniższym przykładzie:

Wskaźniki i operatory

Należy dodatkowo uważać na NULL-owe wskaźniki. Próba dobrania się do ich wartości poskutkuje wyjątkiem: Czytaj dalej

Qt4: konwersja projektu qmake do CMake

Podczas tworzenia projekt w Qt4 z poziomu QtCreatora, do budowania projektu (generowania plików Makefile i tak dalej) QtCreator używa narzędzia qmake. Okazuje się jednak, że to nie wszystko:) QtCreator potrafi także używać CMake! Niestety nie ma póki co gotowego narzędzia, które automatycznie przekonwertuje projekt z qmake na CMake. Możemy jednak zrobić to sami. Jak? O tym jest właśnie ten tutorial.

Zagmatwane jak Qt4 i CMake!

Tworzymy CMakeLists.txt

Na sam początek warto wiedzieć, że sercem CMake jest plik CMakeLists.txt. To w nim definiowane są zasady, jakie biblioteki trzeba znaleźć i dołączyć, które pliki zbudować itd.

W pierwszym kroku trzeba zatem utworzyć plik CMakeLists.txt. Dodajemy go w głównym katalogu projektu. Natomiast folder wyżej (ponad źródłami i plikiem CMakeLists.txt) warto stworzyć dodatkowy folder, w którym będzie budowany nasz program.

Oto wersja pierwsza przykładowego pliku CMakeLists.txt – oferuje automatyczne wyszukiwanie plików ui i moc i generowanie na tej podstawie kodu. Odpowiadają za to zmienne: CMAKE_AUTOMOC i CMAKE_AUTOUIC.

CMAKE_MINIMUM_REQUIRED(VERSION 2.6)

set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)

PROJECT(V1)

set(QT_SRC ${QT_SRC} "${PROJECT_SOURCE_DIR}")
https://wiki.qt.io/Using_CMake_build_system
FIND_PACKAGE(Qt4 REQUIRED QtGui QtXml)
INCLUDE(${QT_USE_FILE})

QT4_WRAP_UI(UISrcs mainwindow.ui)
QT4_WRAP_CPP(MOCSrcs mainwindow.h)
 
include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
INCLUDE_DIRECTORIES(${QT_SRC})
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/src/gui)

add_executable(DemoQt ${PROJECT_SOURCE_DIR}/main.cpp mainwindow)

TARGET_LINK_LIBRARIES(DemoQt Qt4::QtGui Qt4::QtXml) 

Aby wypisać wartości zmiennych, warto użyć polecenia MESSAGE, np.:

MESSAGE("MyProjectLib_src:\t\t${MyProjectLib_src}")

Moje wartości zmiennych są zatem następujące:

MOCSrcs /home/d9k/ProstyProjektQtCmake/qponiższytcreator-build/moc_mainwindow.cxx
MOCSrcs /home/d9k/ProstyProjektQtCmake/qtcreator-build/ui_mainwindow.h
QT_SRC /home/d9k/ProstyProjektQtCmake/zrodla
PROJECT_SOURCE_DIR /home/d9k/ProstyProjektQtCmake/zrodla
QT_USE_FILE /usr/share/cmake-2.8/Modules/UseQt4.cmake
CMAKE_CURRENT_SOURCE_DIR /home/d9k/ProstyProjektQtCmake/zrodla
CMAKE_CURRENT_BINARY_DIR /home/d9k/ProstyProjektQtCmake/qtcreator-build
QT_LIBRARIES /usr/lib/x86_64-linux-gnu/libQtGui.so;/usr/lib/x86_64-linux-gnu/libQtCore.so

Okazuje się jednak, że używanie automatu nie zawsze jest dobre – zwłaszcza, jeśli projekt jest rozbudowany i struktura katalogów jest drzewiasta. Wzorując się na poniższych wpisach w serwisie StackOverflow, udało mi się zmodyfikować poprzednią wersję, aby nie używała automatycznego przypisywania plików ui i moc.

Przechodzimy na sterowanie manualne

Usuwamy zatem fragment ze zmiennymi CMAKE_AUTOMOC i CMAKE_AUTOUIC, by zastąpić go własnym wskazaniem ścieżek: Czytaj dalej

Examples of QString::number

Some examples of a very useful Qt function: QString::number. This function is helpful in converting double/float to string. QString, to be more precise 😉

QString::number has got 3 parameters:

  • double n – number, which will be converted
  • char format = 'g – format: available formats are f, e, E, g, G. Default is 'g’:
  • int precision = 6 – precision.

QString::number – examples

Let me show some examples. On the end of each line is a output from console:


//f - float
QString::number(3.14159265359, 'f', 0); //3
QString::number(3.14159265359, 'f', 1); //3.1
QString::number(3.14159265359, 'f', 2); //3.14
QString::number(3.14159265359, 'f', 15);//3.141592653590000

//e - exponential notation
QString::number(3.14159265359, 'e', 15); //3.141592653590000e+00
QString::number(3.14159265359, 'E', 15); //3.141592653590000E+00

//g/G - "general" - in this case: "f"
QString::number(3.14159265359, 'g', 0); //3
QString::number(3.14159265359, 'g', 1); //3
QString::number(3.14159265359, 'g', 2); //3.1
QString::number(3.14159265359, 'g', 15); //3.14159265359

QString::number(3.14159265359, 'G', 2); //3.1
QString::number(3.14159265359, 'G', 15); //3.14159265359

//g/G - "general" - in this case: "e/E"
QString::number(2.5e+5, 'g', 0); //2e+05
QString::number(2.5e+5, 'g', 1); //2e+05
QString::number(2.5e+5, 'g', 2); //2.5e+05
QString::number(2.5e+5, 'g', 15); //250000

QString::number(2.5e+5, 'G', 2); //2.5E+05
QString::number(2.5e+5, 'G', 15); //250000

//comparision with f and e/E:
QString::number(2.5e+5, 'f', 2); //250000.00

QString::number(2.5e+5, 'e', 15); //2.500000000000000e+05
QString::number(2.5e+5, 'E', 2); //2.50E+05

Parsowanie ciągu znaków do double w C

Parsowanie ciągu znaków do double jest osiągalne w C dzięki funkcji strtod. Jest to dość stara funkcja, obecna w standardzie C90 (z roku 1990).

Składnia to:

double strtod (const char* str, char** endptr);

 

Przykład:

char* pEnd;
double d1;

d1 = strtod ("3.14", &pEnd);
cout << d1 <<endl;//3.14

d1 = strtod ("12,34", &pEnd);
cout << d1 <<endl;//12

d1 = strtod ("-1.55211e-016", &pEnd);
cout << d1 <<endl;//-1.55211e-16

d1 = strtod ("8.67548e-017", &pEnd);
cout << d1 <<endl;//8.67548e-17

d1 = strtod ("8.67548e+1017", &pEnd);
cout << d1 <<endl;//inf

d1 = strtod ("abc", &pEnd);
cout << d1 <<endl;//0

d1 = strtod ("", &pEnd);
cout << d1 <<endl;//0

d1 = strtod (NULL, &pEnd);
cout << d1 <<endl;//exit!

Qt i problemy z atof()

W projekcie, nad którym aktualnie pracuję, natknęłam się na pewien problem, który spowodował nieprawidłowe działanie dużego fragmentu aplikacji napisanej w C, dołączonej do interfejsu implementowanego w Qt (używam wersji 4.8.0, choć nie ma to zbyt wielkiego znaczenia).

Okazało się że część analityczna programu używała  w wielu miejscach funkcji atof() do przekształcania liczb zapisanych w pliku w postaci ddd.ddd (separatorem była zatem kropka).

#include <cstdlib>
double atof( const char * str );

Funkcja nie odczytywała części dziesiętnych z powodu nieprawidłowego traktowania separatora. Ten poważny błąd, uniemożliwiający działanie całego programu wystarczyło naprawić jedną linijką:

setlocale(LC_NUMERIC,"C");

Linijkę tę należy umieścić w pliku main.cpp, tuż po utworzeniu obiektu typu QApplication. Teraz mój plik wygląda następująco:

#include <QtGui/QApplication>
#include "mainwindow.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    setlocale(LC_NUMERIC,"C");

    MainWindow w;
    w.show();

    return a.exec();
}

I – wszystko działa 🙂

Wyświetlanie kodu znaków

Jak uzyskać kod znaku? Pisałam o wyświetlaniu kodów znaków przez linuksową aplikację. Można jednak napisać swój program, który jest banalny w swej prostocie – zwłaszcza w C. I działa niezależnie od systemu:)

W tym celu wystarczy wyświetlić znak (char) jako liczbę (int), np.:

printf("znak entera: %d\n", '\n');
printf("znak spacji: %d\n", ' ');
printf("znak r: %d\n", '\r');
printf("znak a: %d\n", 'a');

Takie rozwiązanie często pojawia się w prostych konsolowych programach, w których nawigacja po aplikacji opiera się o konkretne znaki specjalne, gdzie w pętli while sprawdzamy, czy wpisany znak jest konkretnym klawiszem nawigacyjnym. Jeśli tak, wykonujemy przypisane mu akcje.