Const string паскаль ошибка

Hello I have been given the task of reading file input of 3 digit month abbreviations and a day and I must calculate the Julian date for each (sum of days since jan 1)
No matter what I do when I add two INTEGERS I get error 201 (incompatible data types). I have tried making a new program and gotten it to work but once I implement it into my existing code it doesn’t work anymore. This is very frustrating, please help. I’m sick of this stupid class making me take this language where I can’t find shit online to help.
Here is the code:

program prg6_150;
const
      MONABV:array[1..12] of string[03] = ('JAN','FEB','MAR','APR','MAY','JUN',
                                           'JUL','AUG','SEP','OCT','NOV','DEC');
      MONDAYS:array[1..12] of integer = (31,28,31,30,31,30,31,31,30,31,30,31);

var
      more_rec:Boolean;                    { EOF flag }
      DAY:integer;                         { input day }
      MONTH:string[03];                    { input month abbreviation }
      JULIAN:integer;                      { computed Julian day }
      ch:char;                             { spacer character for input }
      FileIn:Text;
      FileOut:Text;

{ your module, to be called "JULIAN_DAY" inserted here }


    procedure JULIAN_DAY;
    var
    j,sum_days:integer;
    begin
    j := 0;
    sum_days := 0;
    if MONTH = 'JAN' then j := 1 else
    if MONTH = 'FEB' then j := 2 else
    if MONTH = 'MAR' then j := 3 else
    if MONTH = 'APR' then j := 4 else
    if MONTH = 'MAY' then j := 5 else
    if MONTH = 'JUN' then j := 6 else
    if MONTH = 'JUL' then j := 7 else
    if MONTH = 'AUG' then j := 8 else
    if MONTH = 'SEP' then j := 9 else
    if MONTH = 'OCT' then j := 10 else
    if MONTH = 'NOV' then j := 11 else
    if MONTH = 'DEC' then j := 12; 
    for J:= 2 to 12 do
    repeat
        sum_days := MONDAYS[1] + sum_days;
        j := j - 1
    until j = 1;
    Julian := DAY + sum_days;
    end;

    procedure read_rec;
    begin
      if Eof(FileIn) then
        more_rec := False
      else
        readln(FileIn,day,ch,month)
    end;  { read_rec }

    procedure initialize;
    begin
      more_rec := True;
      Assign(FileIn,'JULIAN.DAT');
      Reset(FileIn);
      Assign(FileOut,'JULIAN.OUT');
      Rewrite(FileOut);
      read_rec
    end;  { initialize }

    procedure process;
    begin
      Julian_Day;
      writeln(FileOut,day:2,' ',month,' ',julian:3);
      read_rec
    end;  { process }

    procedure wrapup;
    begin
      Close(FileOut);
      Close(FileIn)
    end;  { wrapup }

    begin  { main }
      initialize;
      while more_rec do
        process;
      wrapup
    end.

Command Prompt Error

My program has following code:

function FooBar(const s: string): string;
var
  sa: AnsiString;
begin

  // ..........................

  sa := AnsiString(s);
  sa := AnsiString(StringReplace(string(sa), '*', '=', [rfReplaceAll]));
  sa := AnsiString(StringReplace(string(sa), ' ', '+', [rfReplaceAll]));
  result := string(sa);

  // ..........................

end;

I noticed that the program did crash «somewhere» and FastMM4 said that I had written to a freed object. As soon as I have commented out «const», the program did work.

I have read the Delphi documentation about const arguments, but I can’t figure out why the const argument crashes the program. I would love to understand it.

UPDATE: The program does only crash in Delphi 6 and only if optimization is ON. If the optimization is OFF, the program will work normally. Might it be a Delphi bug?

asked Apr 29, 2014 at 10:39

Daniel Marschall's user avatar

Daniel MarschallDaniel Marschall

3,7402 gold badges27 silver badges67 bronze badges

8

There are a few peculiar gotchas when it comes to const string parameters.
Many years ago I helped a colleague resolve a similar peculiar problem (D3 iirc). The following simplified example doesn’t look like your specific issue, but it may give you some ideas:

type
  TMyClass
    FString: string;
    procedure AppendString(const S: string);
  end;

procedure TMyClass.AppendString;
begin
  FString := FString + S;
end;

Now if you have an instance of TMyClass and try to call AppendString(FString); to double up the string, you may get an access violation. (There are a few other factors that can affect if you do.) The reason is as follows:

  • The const prevents refcounting the string on the method call.
  • So FString may have refCount = 1 when its value is changed.
  • In which case Copy-on-Write doesn’t apply and the string is reallocated. (Most likely at a different address.)
  • So when the method returns, S is referring to an invalid address, and triggers an AV.

answered Apr 29, 2014 at 14:24

Disillusioned's user avatar

DisillusionedDisillusioned

14.6k3 gold badges43 silver badges77 bronze badges

1

For this case:

 sa := s;

automatic reference counting (ARC) works. This is idiomatic way, compiler know how to work with these string — if sa will change, it creates new copy and so on.

For case of hard typecasting (though type is the same)

sa := AnsiString(s);

you tell compiler that you want to get only pointer to string, and you know how to work with this string reference. Compiler will not interfere and annoy you, but you are responsible for correct operations

P.S. I can not reproduce the problem with Delphi XE5 — both simple assigning and typecasting causes LStrLAsg (internal function) call with ARC. (Of course, compiler magic could be changed a bit)

answered Apr 29, 2014 at 13:53

MBo's user avatar

4

We debugged a crash today that was a Delphi 5 compiler code-gen bug:

procedure TForm1.Button1Click(Sender: TObject);
var
   s: string;
begin
   s := 'Hello, world! '+IntToStr(7);
   DoSomething(s);

   //String s now has a reference count of zero, and has already been freed
   ShowMessage(s);
end;

procedure TForm1.DoSomething(const Title: string);
var
    s: AnsiString;
begin
    s := AnsiString(Title);

    if Now = 7 then
        OutputDebugString('This is a string that is irrelevant');
end;

The Delphi 5 compiler mistakenly tries to decrement the reference counts of both

  • Title
  • s

and causes the const string’s reference count to go to zero. This causes it to be freed. So when DoSomething returns, you are using a freed string.

An access violation waiting to happen.

Or, in the case of customers: happening.

answered Oct 19, 2016 at 19:54

Ian Boyd's user avatar

Ian BoydIan Boyd

245k252 gold badges865 silver badges1206 bronze badges

That becouse AnsiString is a pointer. So, you could’n operate it as a usual strings (which mean a array of chars). Crash is random, so you can gain the crash as result of stackoverflow or access violations at any time, not depend on optimization.

Than you function FooBar return the result, sa variable are already free from mamory.

Try to use the PChar or PAnsiChar and allocate the memory for this variables as your needs.

answered Apr 29, 2014 at 11:17

Y.N's user avatar

Y.NY.N

4,9397 gold badges33 silver badges61 bronze badges

2

Since it doesn’t make sense to convert to AnsiString and back here, I would rewrite this as

function FooBar(const s:string):string;
begin
  Result:=
    StringReplace(
    StringReplace(
      s
      ,'*','=',[rfReplaceAll])
      ,' ','+',[rfReplaceAll]);
end;

answered Apr 29, 2014 at 12:06

Stijn Sanders's user avatar

Stijn SandersStijn Sanders

35.9k11 gold badges45 silver badges67 bronze badges

3

Есть такое понятие в программировании — безопасный код.
Помимо всего прочего (про exceptionы и потокобезопасность здесь речь не пойдет) оно включает в себя стиль написания программы, который не допускает работу с указателями в явной форме — получение, разыменование, арифметика на ним, также не приветствуются операции приведения типов.

Вместо указателей настоятельно рекомендуется использовать ссылки, а типы преобразовывать в явном виде — через операции присваивания, встроенные функции и т.п.

Т.е. нужно как можно больше работы сбрасывать на компилятор — статический контроль типов, управление памятью и прочую рутину. Он умеет это лучше чем человек.

Теперь по поводу совместимости и эквивалентности.

Совместимость типов — это такое отношение между двумя типами, которое доступно компилятору на этапе синтаксического анализа исходника. Т.е. компилятор ЗНАЕТ как перевести тип А в тип Б.
Например real совместим с integer (переменной типа real можно присвоить значение переменной типа integer), но не наоборот.

Эквивалентность типов — имеется в виду двоичная эквивалентность, это отношение между типами, выстроенное на основе размера памяти в байтах, который занимает переменная того или иного типа.
Например у нас есть запись вида:

Код

TMyDWord = packed record
    HiWord: Word;
    LoWord: Word;
end;

Если мы имеем переменную типа Dword то мы вполне можем привести её к типу TMyDWord. Это приведение допустимо потому что размер занимаемый TMyDword равен размеру DWord. Обратное приведение также возможно.
Эквивалентность типов может зависеть от настроек компилятора. Если мы поставим выравнивание полей записи по 4 байтам (это сильно ускорит их обработку) приведенный выше пример не будет работать, так как размеры перестанут совпадать и отношение двоичной эквивалентности между типами пропадет.

Операция приведения типа оперирует с понятием эквивалентности типов. Мы можем привести тип А к типу Б в том случае, когда size(А) >= size(Б). Это ограничение не позволит обратиться к, возможно, невыделенной области памяти, что приведет к AV-исключению.

При передаче параметров в подпрограммы или методы, для компилятора очень важен ТИП подставляемх фактических параметров, именно на основе их типов, он будет вызывать нужную перегруженную версию (если они есть) сабрутины. Отсюда правило — нужно ЗНАТЬ что ты хочешь сделать, чтобы небыло недопонимания с компилером.

Цитата

Мне кажется, что оба действия — и Type1(Type2Variable) и Type1((@Type2Variable)^) — выполняются на этапе
компиляции. Но почему в первом случае создаётся локальная копия(для VAR-параметров), по какому синтаксическому правилу?

Я уже объяснял….. Первый вариант приводит к копированию данных во временную переменную. Второй вариант компилятор рассматривает как некое переобъявление переменной. Разыменованный указатель — это переменная, операция приведения типа выступает в качестве декларирования типа переменной. Именно поэтому такая запись пригодна для передачи параметра по ссылке.

Добавлено через 6 мин.
Ваял предыдущий креатив…..

Цитата(Neznaika @ 11.08.2007 18:41) *

А можно ли вообще использовать в качестве фактических параметров процедур для VAR-параметров ВЫРАЖЕНИЯ? Для W типа Word конструкция Byte(W) — это выражение.

В принципе — можно. Если выражение своим результатом возвращает указатель, то используя технику дзен

Код

Type1((PType1PointerExpression)^)

Мы можем передавать данные по ссылке.
Другое дело, что нам потребуется написать выражение, результатом которого будет некий указаталь (с точки зрения безопасного кода подобные действия никуда не годятся).

Program_LABA9.pas(100,43) Error: Incompatible type for arg no. 2: Got «Constant String», expected «LongInt» — Free Pascal

Формулировка задачи:

Помогите решить проблему Program_LABA9.pas(100,43) Error: Incompatible type for arg no. 2: Got «Constant String», expected «LongInt»

Код к задаче: «Program_LABA9.pas(100,43) Error: Incompatible type for arg no. 2: Got «Constant String», expected «LongInt»»

textual

Листинг программы

Полезно ли:

12   голосов , оценка 3.917 из 5

Похожие ответы

  1. Ввести x с клавиатуры и определить, сколько чисел в промежутке от 1 до 100 делятся без остатка на x, x-1 или x
  2. Выдать все четные числа от 0 до 10000, если х = 0; иначе выдать x^5
  3. Разбросать по экрану 1000 звездочек в случайном месте случайным цветом с небольшой задержкой
  4. Ошибка: syntax error identifier expected
  5. Ошибка fatal: syntax error identifier expected
  6. Ошибка при компиляции «Syntax error «Begin» expected but «;» found»
  7. Ошибка «Syntax Error, «:» expected but «;» found
  8. Вычислить 100!+2^100
  9. Найти сумму первых 100 элементов упорядоченной последовательности
  10. При выполнении программы пропускается цикл for
  11. Как наиболее рационально обратиться к элементам динамического массива через цикл For

Ниже мой код, а затем ниже, это сообщение об ошибке. Буду признателен за любую помощь. Спасибо. Назначение:

« Измените предоставленный класс String чтобы внутренне хранить строки Pascal, которые представляют собой массивы символов, которые начинаются с нескольких символов в строке, за которыми следуют эти символы, без конечного нулевого символа. То есть:

  • str должна содержать строку Pascal.
  • Должен быть включен конструктор, созданный в вашей строковой лаборатории Pascal. Также должен быть включен нормальный конструктор C-строк и должен преобразовать его в строку Pascal.
  • Функция c_str должна преобразовать обратно в строку C, чтобы предоставить пользователю строку C. В этой функции можно выделить память для строки.
  • Все остальные функции должны выполняться правильно, учитывая изменение во внутреннем формате строки.
  • Вы не можете хранить строку C внутри себя вместе с строкой Pascal.

Pascal.cpp

// Pascal Main cpp


#include <iostream>
#include <algorithm>
#include "Pascal.h"
#include <exception>
using namespace std;
// Default constructor
String::String() {
    arr = new char[1];
    arr[0] = '';
    len = 0;
}

// Constructor. Converts a C-string to a String object
String::String(const char *s) {
    len = strlen(s);
    arr = new char[len + 1];
    std::copy(s, s + len + 1, arr);
}

// Copy constructor.
String::String(const String &obj) {
    len = obj.len;
    arr = new char[len + 1];
    std::copy(obj.arr, obj.arr + len + 1, arr);
}

// Move constructor.
String::String(String &&obj) {
    len = obj.len;
    arr = obj.arr;
    obj.arr = nullptr;
}

String::String(const char *str, bool pascal) {
    judge = pascal;
    if (judge) {
        len = strlen(str) - 1;
        const char *temp = str;
        arr = new char[len + 1];
        arr[0] = len + '0';
        for (int i = 1; i <= len; i++) {
            arr[i] = temp[i];
        }

    }
    else {
        len = strlen(str);
        arr = new char[len + 1];
        std::copy(str, str + len + 1, arr);
    }
}

// Destructor
String::~String() {
    if (arr != nullptr)
        delete[] arr;
}

// Assignment operator
String &String::operator=(const String &rhs) {
    delete[] arr;
    len = rhs.len;
    arr = new char[len + 1];
    std::copy(rhs.arr, rhs.arr + len + 1, arr);
    return *this;
}

// Move assignment operator
String &String::operator=(String &&rhs) {
    delete[] arr;
    len = rhs.len;
    arr = rhs.arr;
    rhs.arr = nullptr;
    return *this;
}


// Mutator operator[]
char &String::operator[](int index) {
    // check whether the index is within bounds
    if (index > len || index < 0)
        throw std::out_of_range("Index out of range");
    return arr[index];
}

// Accessor operator[]
char String::operator[](int index) const {
    // check whether the index is within bounds
    if (index > len || index < 0)
        throw std::out_of_range("Index out of range");
    return arr[index];
}

// Get the length (number of characters) of a String object
int String::length() const {
    return len;
}

bool operator==(const String &lhs, const String &rhs) {
    if (lhs.judge != rhs.judge) {
        cout << "can't compare";
    }
    return strcmp(lhs.arr, rhs.arr) == 0;
}

bool operator<(const String &lhs, const String &rhs) {
    if (lhs.judge != rhs.judge) {
        cout << "can't compare";
    }
    return strcmp(lhs.arr, rhs.arr) < 0;
}

// Friend functions for > comparison
bool operator>(const String &lhs, const String &rhs) {
    if (lhs.judge != rhs.judge) {
        cout << "can't compare";
    }
    return rhs < lhs;
}

// Friend functions for <= comparison
bool operator<=(const String &lhs, const String &rhs) {
    if (lhs.judge != rhs.judge) {
        cout << "can't compare";
    }
    return !(rhs < lhs);
}

// Friend functions for >= comparison
bool operator>=(const String &lhs, const String &rhs) {
    if (lhs.judge != rhs.judge) {
        cout << "can't compare";
    }
    return !(lhs  < rhs);
}

// Friend functions for != comparison
bool operator!=(const String &lhs, const String &rhs) {
    if (lhs.judge != rhs.judge) {
        cout << "can't compare";
    }
    return !(lhs == rhs);
}

//  Friend function for string concatination
String operator+(const String &lhs, const String &rhs) {
    if (lhs.judge == rhs.judge && lhs.judge == false) {
        int strLength = lhs.len + rhs.len + 1;
        char *tmpStr = new char[strLength];
        for (auto i = 0; i < lhs.len; ++i)
            tmpStr[i] = lhs.arr[i];
        for (auto i = 0; i <= rhs.len; ++i)
            tmpStr[lhs.len + i] = rhs.arr[i];
        String retStr(tmpStr);
        delete[] tmpStr;
        return retStr;
    }
    else if (lhs.judge == rhs.judge && lhs.judge == true) {
        int strLength = lhs.len + rhs.len + 1;
        char *tmp = new char[strLength];
        for (auto i = 1; i <= lhs.len; ++i)
            tmp[i] = lhs.arr[i];
        for (auto i = 1; i <= rhs.len; ++i)
            tmp[lhs.len + i] = rhs.arr[i];
        tmp[0] = (lhs.len + rhs.len) + '0';
        String retStr(tmp);
        delete[] tmp;
        return retStr;
    }
    else {
        return String("can't do that");
    }
}

// Return C style character string
const char* String::c_str() const {
    return arr;
}

//  Friend function for output
std::ostream& operator<<(std::ostream &out, const String &obj) {
    return out << obj.c_str();
}

Pascal.h

// Pascal Header File

#pragma once
#ifndef __MYSTRING_H__
#define __MYSTRING_H__

#include <iostream>

class String {
public:
    // Usage: String aStringObj; or String aStringObj();
    String();

    // Constructor. Converts a char* object to a String  object
    // Usage: String aStringObj("hello"); or String aStringObj = "hello";
    String(const char *s);

    // Copy and move constructors.
    // Usage: String aStringObject(anotherStringObj); or
    // String aStringObject = anotherStringObj;
    String(const String &s);
    String(const char *str, bool pascal);
    String(String&& obj);

    // Destructor
    ~String();

    // Assignment operator
    // Usage: aStringObject = anotherStringObj; or
    // aStringObject.operator=(anotherStringObj);
    String &operator=(const String &rhsObject);
    String& operator=(String&& rhs);

    // Mutator operator[]
    // Usage: aStringObject[1] = M;
    char &operator[] (int index);

    // Accessor operator[]
    // Usage: char ch = aStringObject[1];
    char operator[] (int index) const;

    // Get the length (number of characters) of a String object
    // Usage: int len = aStringObject.Length();
    int length() const;

    // Friend functions for == comparison
    // Usage: if (aStringObject == anotherStringObj) {...} or
    //        if (aStringObject == "hello") {...} or
    //        if ("hello" == aStringObj) {...} or
    friend bool operator==(const String &lhsObject, const String &rhsObject);

    // The other five comparison operators
    // !=, <, >, <=, >= are similarly handled as in line 13.

    friend bool operator<(const String &lhsObject, const String &rhsObject);
    friend bool operator>(const String &lhsObject, const String &rhsObject);
    friend bool operator<=(const String &lhsObject, const String &rhsObject);
    friend bool operator>=(const String &lhsObject, const String &rhsObject);
    friend bool operator!=(const String &lhsObject, const String &rhsObject);

    // Friend function for string concatenation
    // Usage: StringOne = StringTwo + StringThree  or
    //        StringOne = "hello" + StringTwo  or
    //        StringOne = StringTwo + "hello"
    friend String operator+(const String &lhs, const String &rhs);

    // Return C style character string
    // Usage: const char *str = aStringObj.C_str();
    const char *c_str() const;

    // Friend function for output
    // Usage: cout << aStringObj;
    friend std::ostream &operator<<(std::ostream &out, const String &obj);

private:
    // arr implements the String object as a dynamic array
    char *arr;

    // len keeps track of the length
    int len;

    // judge weather the String is a c_string or a pascal_string
    bool judge;
};

#endif

При компиляции я получаю эти предупреждения и ошибки:

Изображение 376128

Severity    Code    Description Project File    Line    Suppression State
Warning C4996   'std::_Copy_impl': Function call with parameters that may be unsafe - this call relies on the caller to check that the passed values are correct. To disable this warning, use -D_SCL_SECURE_NO_WARNINGS. See documentation on how to use Visual C++ 'Checked Iterators'    Pascal Assignment   c:program files (x86)microsoft visual studio 14.0vcincludexutility 2229    

 Severity   Code    Description Project File    Line    Suppression State
Error   LNK1120 1 unresolved externals  Pascal Assignment   C:UsersDanielleDocumentsVisual Studio 2015ProjectsPascal AssignmentDebugPascal Assignment.exe   1   

Severity    Code    Description Project File    Line    Suppression State
Error   LNK2019 unresolved external symbol _main referenced in function "int __cdecl invoke_main(void)" (?invoke_main@@YAHXZ)   Pascal Assignment   C:UsersDanielleDocumentsVisual Studio 2015ProjectsPascal AssignmentMSVCRTD.lib(exe_main.obj) 1   

  • Connection timeout как исправить ошибку
  • Connection refused ошибка кассы
  • Connection closed without indication ошибка ftp
  • Connection attempt has timed out please verify internet connectivity как исправить ошибку
  • Connecting произошла ошибка при загрузке скетча